Skip to content

Commit 3d61bf9

Browse files
refactor: quarto
1 parent 0862d37 commit 3d61bf9

2 files changed

Lines changed: 58 additions & 104 deletions

File tree

‎quarto/main.go‎

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
1-
// A generated module for Quarto functions
1+
// A Dagger module for authoring, rendering, and publishing Quarto projects.
22
//
3-
// This module has been generated via dagger init and serves as a reference to
4-
// basic module structure as you get started with Dagger.
5-
//
6-
// Two functions have been pre-created. You can modify, delete, or add to them,
7-
// as needed. They demonstrate usage of arguments and return types using simple
8-
// echo and grep commands. The functions can be called from the dagger CLI or
9-
// from one of the SDKs.
10-
//
11-
// The first line in this comment block is a short description line and the
12-
// rest is a long description with more detail on the module's purpose or usage,
13-
// if appropriate. All modules should have a short description.
3+
// This module provides tools to render Quarto documents, books, websites,
4+
// install custom Quarto extensions, and manage LaTeX packages via TeX Live.
145
package main
156

167
import (
@@ -19,11 +10,11 @@ import (
1910
)
2011

2112
const (
22-
defaultImageRepository = "ghcr.io/quarto-dev/quarto"
13+
defaultImageRepository = "ghcr.io/quarto-dev/quarto:latest"
2314
tlmgrUpdateURL = "https://mirror.ctan.org/systems/texlive/tlnet/update-tlmgr-latest.sh"
2415
)
2516

26-
// Quarto is a module for running Quarto
17+
// Quarto provides functions for running and compiling Quarto projects.
2718
type Quarto struct {
2819
// +private
2920
Image string
@@ -35,15 +26,15 @@ type Quarto struct {
3526
Ctr *dagger.Container
3627
}
3728

38-
// New creates a new instance of the Quarto struct
29+
// New creates a new instance of the Quarto module.
3930
func New(
4031
// Custom image reference in "repository:tag" format to use as a base container.
4132
// +optional
4233
image string,
43-
// List of extensions to add to the container.
34+
// List of Quarto extensions to install (e.g. "quarto-ext/lightbox").
4435
// +optional
4536
extensions []string,
46-
// List of optional LaTeX packages to install.
37+
// List of optional LaTeX packages to install via tlmgr (requires a TeX-enabled image like quarto-full).
4738
// +optional
4839
latexPackages []string,
4940
) *Quarto {
@@ -54,7 +45,7 @@ func New(
5445
}
5546
}
5647

57-
// Container returns the underlying Dagger container
48+
// container returns the underlying Dagger container, lazily initialized.
5849
func (m *Quarto) container() *dagger.Container {
5950
if m.Ctr != nil {
6051
return m.Ctr
@@ -67,20 +58,19 @@ func (m *Quarto) container() *dagger.Container {
6758

6859
ctr := dag.Container().From(image)
6960

70-
if strings.Contains(image, "quarto-full") {
71-
// Update tlmgr
61+
// Only update tlmgr and install packages if LaTeX packages are explicitly requested
62+
if len(m.LatexPackages) > 0 {
7263
ctr = ctr.WithExec([]string{
7364
"sh", "-c",
7465
"curl -fsSL " + tlmgrUpdateURL + " -o update-tlmgr-latest.sh && sh update-tlmgr-latest.sh -- --update",
7566
})
7667

77-
// Install specified LaTeX packages
78-
for _, pkg := range m.LatexPackages {
79-
ctr = ctr.WithExec([]string{"tlmgr", "install", pkg})
80-
}
68+
// Install all packages in a single command layer
69+
installCmd := append([]string{"tlmgr", "install"}, m.LatexPackages...)
70+
ctr = ctr.WithExec(installCmd)
8171
}
8272

83-
// Add Quarto extensions
73+
// Install Quarto extensions
8474
for _, ext := range m.Extensions {
8575
ctr = ctr.WithExec([]string{"quarto", "add", "--no-prompt", ext})
8676
}
@@ -89,35 +79,41 @@ func (m *Quarto) container() *dagger.Container {
8979
return m.Ctr
9080
}
9181

92-
// Build runs the quarto render command exporting to a directory
82+
// Build compiles the Quarto project and returns the exported output directory.
9383
func (m *Quarto) Build(
94-
// source directory.
84+
// Source directory of the Quarto project.
9585
source *dagger.Directory,
86+
// Output directory name relative to source (e.g. "_output", "_site", "_book").
87+
// +default="_output"
88+
// +optional
89+
outputDir string,
9690
) *dagger.Directory {
91+
workdir := "/work"
92+
outPath := workdir + "/" + strings.TrimPrefix(outputDir, "/")
93+
9794
return m.container().
98-
WithDirectory("/tmp", source).
99-
WithWorkdir("/tmp").
100-
WithExec([]string{"quarto", "render"}).Directory("/tmp/_output")
95+
WithMountedDirectory(workdir, source).
96+
WithWorkdir(workdir).
97+
WithExec([]string{"quarto", "render"}).
98+
Directory(outPath)
10199
}
102100

103-
// Render runs the quarto render command
101+
// Render runs the quarto render command and returns the container.
104102
func (m *Quarto) Render(
105-
// source directory.
103+
// Source directory of the Quarto project.
106104
source *dagger.Directory,
107105
) *dagger.Container {
108106
return m.container().
109-
WithDirectory("/tmp", source).
110-
WithWorkdir("/tmp").
107+
WithMountedDirectory("/work", source).
108+
WithWorkdir("/work").
111109
WithExec([]string{"quarto", "render"})
112110
}
113111

114-
// Cli runs the quarto cli
112+
// Cli executes an arbitrary command in the Quarto container.
115113
func (m *Quarto) Cli(
116-
// commands to run
114+
// Command string to execute (e.g. "quarto --version" or "quarto check").
117115
args string,
118116
) *dagger.Container {
119-
parsedArgs := strings.Split(args, " ")
120-
121117
return m.container().
122-
WithExec(parsedArgs)
118+
WithExec([]string{"sh", "-c", args})
123119
}

‎quarto/test/main.go‎

Lines changed: 23 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,19 @@
1-
// A generated module for Quartotest functions
2-
//
3-
// This module has been generated via dagger init and serves as a reference to
4-
// basic module structure as you get started with Dagger.
5-
//
6-
// Two functions have been pre-created. You can modify, delete, or add to them,
7-
// as needed. They demonstrate usage of arguments and return types using simple
8-
// echo and grep commands. The functions can be called from the dagger CLI or
9-
// from one of the SDKs.
10-
//
11-
// The first line in this comment block is a short description line and the
12-
// rest is a long description with more detail on the module's purpose or usage,
13-
// if appropriate. All modules should have a short description.
1+
// Package main provides test suites for the Quarto Dagger module.
142
package main
153

164
import (
175
"context"
186
"dagger/quarto/test/internal/dagger"
19-
"os"
20-
"regexp"
7+
"errors"
8+
"strings"
219

2210
"github.com/sourcegraph/conc/pool"
2311
)
2412

25-
// Quartotest is a Dagger module that provides functions for running Quarto.
13+
// Quartotest provides tests for the Quarto module.
2614
type Quartotest struct{}
2715

28-
// All runs all tests.
16+
// All runs all tests concurrently.
2917
func (m *Quartotest) All(ctx context.Context) error {
3018
p := pool.New().WithErrors().WithContext(ctx)
3119

@@ -38,9 +26,8 @@ func (m *Quartotest) All(ctx context.Context) error {
3826
return p.Wait()
3927
}
4028

41-
// Extensions add quarto extensions to the container.
29+
// Extensions tests installing Quarto extensions.
4230
func (m *Quartotest) Extensions(ctx context.Context) error {
43-
4431
_, err := dag.Quarto(
4532
dagger.QuartoOpts{
4633
Extensions: []string{
@@ -50,18 +37,14 @@ func (m *Quartotest) Extensions(ctx context.Context) error {
5037
},
5138
).Cli("quarto --version").Sync(ctx)
5239

53-
if err != nil {
54-
return err
55-
}
56-
57-
return nil
40+
return err
5841
}
5942

60-
// Build runs the quarto build command.
43+
// Build tests compiling a document to PDF and verifies the output artifact.
6144
func (m *Quartotest) Build(ctx context.Context) error {
62-
6345
dir := dag.CurrentModule().Source().Directory("./testdata")
64-
outputdata, err := dag.Quarto(
46+
47+
outputDir, err := dag.Quarto(
6548
dagger.QuartoOpts{
6649
Image: "ghcr.io/quarto-dev/quarto-full",
6750
},
@@ -70,73 +53,48 @@ func (m *Quartotest) Build(ctx context.Context) error {
7053
return err
7154
}
7255

73-
outputDir := "./outputdata"
74-
_, err = outputdata.Export(ctx, outputDir)
75-
if err != nil {
76-
return err
77-
}
78-
79-
files, err := os.ReadDir(outputDir)
56+
// Verify generated files directly inside the Dagger Directory (no host disk writes needed)
57+
entries, err := outputDir.Entries(ctx)
8058
if err != nil {
8159
return err
8260
}
8361

84-
for _, file := range files {
85-
re := regexp.MustCompile(`\.pdf$`)
86-
if re.MatchString(file.Name()) {
87-
return nil
62+
for _, name := range entries {
63+
if strings.HasSuffix(name, ".pdf") {
64+
return nil // PDF successfully generated!
8865
}
8966
}
9067

91-
err = os.RemoveAll(outputDir)
92-
if err != nil {
93-
return err
94-
}
95-
96-
return nil
68+
return errors.New("quarto build succeeded, but no .pdf file was found in output directory")
9769
}
9870

99-
// Render runs the quarto render command.
71+
// Render tests running the render process directly on the container.
10072
func (m *Quartotest) Render(ctx context.Context) error {
101-
10273
dir := dag.CurrentModule().Source().Directory("./testdata")
74+
10375
_, err := dag.Quarto(
10476
dagger.QuartoOpts{
10577
Image: "ghcr.io/quarto-dev/quarto-full",
10678
},
10779
).Render(dir).Sync(ctx)
10880

109-
if err != nil {
110-
return err
111-
}
112-
113-
return nil
81+
return err
11482
}
11583

116-
// FullVersion runs the quarto --version command.
84+
// FullVersion tests the CLI against the quarto-full image.
11785
func (m *Quartotest) FullVersion(ctx context.Context) error {
118-
11986
_, err := dag.Quarto(
12087
dagger.QuartoOpts{
12188
Image: "ghcr.io/quarto-dev/quarto-full",
12289
},
12390
).Cli("quarto --version").Sync(ctx)
12491

125-
if err != nil {
126-
return err
127-
}
128-
129-
return nil
92+
return err
13093
}
13194

132-
// CliVersion runs the quarto --version command.
95+
// Version tests the CLI against the default lightweight image.
13396
func (m *Quartotest) Version(ctx context.Context) error {
134-
13597
_, err := dag.Quarto().Cli("quarto --version").Sync(ctx)
13698

137-
if err != nil {
138-
return err
139-
}
140-
141-
return nil
99+
return err
142100
}

0 commit comments

Comments
 (0)