mirror of
https://github.com/Dadido3/go-typst.git
synced 2025-11-20 03:49:34 +00:00
Add DockerExec caller & Add custom Docker CLI options
This commit is contained in:
parent
1f6b0f39a0
commit
245124d082
17
README.md
17
README.md
@ -124,9 +124,24 @@ typstCaller := typst.Docker{
|
||||
err := typstCaller.Compile(input, output, &typst.OptionsCompile{FontPaths: []string{"/fonts"}})
|
||||
```
|
||||
|
||||
### Named Docker containers
|
||||
|
||||
If you have an already running Docker container that you want to (re)use, you can use `typst.DockerExec` to invoke the Typst executable inside any running container by its name:
|
||||
|
||||
```go
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "typst",
|
||||
}
|
||||
|
||||
err := typstCaller.Compile(input, output, options)
|
||||
```
|
||||
|
||||
This method has a lower latency than using `typst.Docker`, as it doesn't need to spin up a Docker container every call.
|
||||
But you need to manage the lifetime of the Container yourself, or use a Docker orchestrator.
|
||||
|
||||
## Caller interface
|
||||
|
||||
`typst.CLI` and `typst.Docker` both implement the `typst.Caller` interface.
|
||||
`typst.CLI`, `typst.Docker` and `typst.DockerExec` implement the `typst.Caller` interface.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
160
docker-exec.go
Normal file
160
docker-exec.go
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2025 David Vogel
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
package typst
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Theoretically it's possible to use the Docker SDK directly:
|
||||
// https://docs.docker.com/reference/api/engine/sdk/examples/
|
||||
// But that dependency is unnecessarily huge, therefore we will just call the Docker executable.
|
||||
|
||||
// DockerExec allows you to invoke Typst commands in a running Docker container.
|
||||
//
|
||||
// This uses docker exec, and therefore needs you to set up a running container beforehand.
|
||||
// For a less complex setup see typst.Docker.
|
||||
type DockerExec struct {
|
||||
ContainerName string // The name of the running container you want to invoke Typst in.
|
||||
TypstPath string // The path to the Typst executable inside of the container. Defaults to `typst` if left empty.
|
||||
|
||||
// Custom "docker exec" command line options go here.
|
||||
// For all available options, see: https://docs.docker.com/reference/cli/docker/container/exec/
|
||||
//
|
||||
// Example:
|
||||
// typst.DockerExec{Custom: []string{"--user", "1000"}} // Use a non-root user inside the docker container.
|
||||
Custom []string
|
||||
}
|
||||
|
||||
// Ensure that DockerExec implements the Caller interface.
|
||||
var _ Caller = DockerExec{}
|
||||
|
||||
// args returns docker related arguments.
|
||||
func (d DockerExec) args() ([]string, error) {
|
||||
if d.ContainerName == "" {
|
||||
return nil, fmt.Errorf("the provided ContainerName field is empty")
|
||||
}
|
||||
|
||||
typstPath := "typst"
|
||||
if d.TypstPath != "" {
|
||||
typstPath = d.TypstPath
|
||||
}
|
||||
|
||||
// Argument -i is needed for stdio to work.
|
||||
args := []string{"exec", "-i"}
|
||||
|
||||
args = append(args, d.Custom...)
|
||||
|
||||
args = append(args, d.ContainerName, typstPath)
|
||||
|
||||
return args, nil
|
||||
}
|
||||
|
||||
// VersionString returns the Typst version as a string.
|
||||
func (d DockerExec) VersionString() (string, error) {
|
||||
args, err := d.args()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
args = append(args, "--version")
|
||||
|
||||
cmd := exec.Command("docker", args...)
|
||||
|
||||
var output, errBuffer bytes.Buffer
|
||||
cmd.Stdout = &output
|
||||
cmd.Stderr = &errBuffer
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
switch err := err.(type) {
|
||||
case *exec.ExitError:
|
||||
return "", ParseStderr(errBuffer.String(), err)
|
||||
default:
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return output.String(), nil
|
||||
}
|
||||
|
||||
// Fonts returns all fonts that are available to Typst.
|
||||
// The options parameter is optional, and can be nil.
|
||||
func (d DockerExec) Fonts(options *OptionsFonts) ([]string, error) {
|
||||
args, err := d.args()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if options == nil {
|
||||
options = new(OptionsFonts)
|
||||
}
|
||||
args = append(args, options.Args()...)
|
||||
|
||||
cmd := exec.Command("docker", args...)
|
||||
|
||||
var output, errBuffer bytes.Buffer
|
||||
cmd.Stdout = &output
|
||||
cmd.Stderr = &errBuffer
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
switch err := err.(type) {
|
||||
case *exec.ExitError:
|
||||
return nil, ParseStderr(errBuffer.String(), err)
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var result []string
|
||||
scanner := bufio.NewScanner(&output)
|
||||
for scanner.Scan() {
|
||||
result = append(result, scanner.Text())
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Compile takes a Typst document from input, and renders it into the output writer.
|
||||
// The options parameter is optional, and can be nil.
|
||||
func (d DockerExec) Compile(input io.Reader, output io.Writer, options *OptionsCompile) error {
|
||||
args, err := d.args()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if options == nil {
|
||||
options = new(OptionsCompile)
|
||||
}
|
||||
args = append(args, options.Args()...)
|
||||
|
||||
cmd := exec.Command("docker", args...)
|
||||
cmd.Stdin = input
|
||||
cmd.Stdout = output
|
||||
|
||||
errBuffer := bytes.Buffer{}
|
||||
cmd.Stderr = &errBuffer
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
switch err := err.(type) {
|
||||
case *exec.ExitError:
|
||||
if err.ExitCode() >= 125 {
|
||||
// Most likely docker related error.
|
||||
// TODO: Find a better way to distinguish between Typst or Docker errors.
|
||||
return fmt.Errorf("exit code %d: %s", err.ExitCode(), errBuffer.String())
|
||||
} else {
|
||||
// Typst related error.
|
||||
return ParseStderr(errBuffer.String(), err)
|
||||
}
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
184
docker-exec_test.go
Normal file
184
docker-exec_test.go
Normal file
@ -0,0 +1,184 @@
|
||||
// Copyright (c) 2025 David Vogel
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
package typst_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/Dadido3/go-typst"
|
||||
)
|
||||
|
||||
func TestDockerExec(t *testing.T) {
|
||||
// Just to ensure that there is no container running.
|
||||
exec.Command("docker", "stop", "-t", "1", "typst-instance").Run()
|
||||
exec.Command("docker", "rm", "typst-instance").Run()
|
||||
|
||||
if err := exec.Command("docker", "run", "--name", "typst-instance", "-v", "./test-files:/test-files", "-id", "123marvin123/typst").Run(); err != nil {
|
||||
t.Fatalf("Failed to run Docker container: %v.", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
exec.Command("docker", "stop", "-t", "1", "typst-instance").Run()
|
||||
exec.Command("docker", "rm", "typst-instance").Run()
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
Name string
|
||||
Function func(*testing.T)
|
||||
}{
|
||||
{"VersionString", dockerExec_VersionString},
|
||||
{"Fonts", dockerExec_Fonts},
|
||||
{"FontsWithOptions", dockerExec_FontsWithOptions},
|
||||
{"FontsWithFontPaths", dockerExec_FontsWithFontPaths},
|
||||
{"Compile", dockerExec_Compile},
|
||||
{"CompileWithWorkingDir", dockerExec_CompileWithWorkingDir},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
test.Function(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func dockerExec_VersionString(t *testing.T) {
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "typst-instance",
|
||||
}
|
||||
|
||||
v, err := typstCaller.VersionString()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get typst version: %v.", err)
|
||||
}
|
||||
|
||||
t.Logf("VersionString: %s", v)
|
||||
}
|
||||
|
||||
func dockerExec_Fonts(t *testing.T) {
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "typst-instance",
|
||||
}
|
||||
|
||||
result, err := typstCaller.Fonts(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get available fonts: %v.", err)
|
||||
}
|
||||
if len(result) < 4 {
|
||||
t.Errorf("Unexpected number of detected fonts. Got %d, want >= %d.", len(result), 4)
|
||||
}
|
||||
}
|
||||
|
||||
func dockerExec_FontsWithOptions(t *testing.T) {
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "typst-instance",
|
||||
}
|
||||
|
||||
result, err := typstCaller.Fonts(&typst.OptionsFonts{IgnoreSystemFonts: true})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get available fonts: %v.", err)
|
||||
}
|
||||
if len(result) != 4 {
|
||||
t.Errorf("Unexpected number of detected fonts. Got %d, want %d.", len(result), 4)
|
||||
}
|
||||
}
|
||||
|
||||
func dockerExec_FontsWithFontPaths(t *testing.T) {
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "typst-instance",
|
||||
}
|
||||
|
||||
result, err := typstCaller.Fonts(&typst.OptionsFonts{IgnoreSystemFonts: true, FontPaths: []string{"/test-files"}})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get available fonts: %v.", err)
|
||||
}
|
||||
if len(result) != 5 {
|
||||
t.Errorf("Unexpected number of detected fonts. Got %d, want %d.", len(result), 5)
|
||||
}
|
||||
}
|
||||
|
||||
// Test basic compile functionality.
|
||||
func dockerExec_Compile(t *testing.T) {
|
||||
const inches = 1
|
||||
const ppi = 144
|
||||
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "typst-instance",
|
||||
}
|
||||
|
||||
r := bytes.NewBufferString(`#set page(width: ` + strconv.FormatInt(inches, 10) + `in, height: ` + strconv.FormatInt(inches, 10) + `in, margin: (x: 1mm, y: 1mm))
|
||||
= Test
|
||||
|
||||
#lorem(5)`)
|
||||
|
||||
opts := typst.OptionsCompile{
|
||||
Format: typst.OutputFormatPNG,
|
||||
PPI: ppi,
|
||||
}
|
||||
|
||||
var w bytes.Buffer
|
||||
if err := typstCaller.Compile(r, &w, &opts); err != nil {
|
||||
t.Fatalf("Failed to compile document: %v.", err)
|
||||
}
|
||||
|
||||
imgConf, imgType, err := image.DecodeConfig(&w)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to decode image: %v.", err)
|
||||
}
|
||||
if imgType != "png" {
|
||||
t.Fatalf("Resulting image is of type %q, expected %q.", imgType, "png")
|
||||
}
|
||||
if imgConf.Width != inches*ppi {
|
||||
t.Fatalf("Resulting image width is %d, expected %d.", imgConf.Width, inches*ppi)
|
||||
}
|
||||
if imgConf.Height != inches*ppi {
|
||||
t.Fatalf("Resulting image height is %d, expected %d.", imgConf.Height, inches*ppi)
|
||||
}
|
||||
}
|
||||
|
||||
// Test basic compile functionality with a given working directory.
|
||||
func dockerExec_CompileWithWorkingDir(t *testing.T) {
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "typst-instance",
|
||||
}
|
||||
|
||||
r := bytes.NewBufferString(`#import "hello-world-template.typ": template
|
||||
#show: doc => template()`)
|
||||
|
||||
var w bytes.Buffer
|
||||
err := typstCaller.Compile(r, &w, &typst.OptionsCompile{Root: "/test-files"})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to compile document: %v.", err)
|
||||
}
|
||||
if w.Available() == 0 {
|
||||
t.Errorf("No output was written.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerExec_EmptyContainerName(t *testing.T) {
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "",
|
||||
}
|
||||
|
||||
_, err := typstCaller.VersionString()
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, but got nil.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerExec_NonRunningContainer(t *testing.T) {
|
||||
typstCaller := typst.DockerExec{
|
||||
ContainerName: "something-else",
|
||||
}
|
||||
|
||||
_, err := typstCaller.VersionString()
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, but got nil.")
|
||||
}
|
||||
}
|
||||
15
docker.go
15
docker.go
@ -22,6 +22,10 @@ import (
|
||||
const DockerDefaultImage = "ghcr.io/typst/typst:0.14.0"
|
||||
|
||||
// Docker allows you to invoke commands on a Typst Docker image.
|
||||
//
|
||||
// This uses docker run to automatically pull and run a container.
|
||||
// Therefore the container will start and stop automatically.
|
||||
// To have more control over the lifetime of a Docker container see typst.DockerExec.
|
||||
type Docker struct {
|
||||
Image string // The image to use, defaults to the latest supported offical Typst Docker image if left empty. See: typst.DockerDefaultImage.
|
||||
WorkingDirectory string // The working directory of Docker. When left empty, Docker will be run with the process's current working directory.
|
||||
@ -33,6 +37,13 @@ type Docker struct {
|
||||
// typst.Docker{Volumes: []string{".:/markup"}} // This bind mounts the current working directory to "/markup" inside the container.
|
||||
// typst.Docker{Volumes: []string{"/usr/share/fonts:/usr/share/fonts"}} // This makes all system fonts available to Typst running inside the container.
|
||||
Volumes []string
|
||||
|
||||
// Custom "docker run" command line options go here.
|
||||
// For all available options, see: https://docs.docker.com/reference/cli/docker/container/run/
|
||||
//
|
||||
// Example:
|
||||
// typst.Docker{Custom: []string{"--user", "1000"}} // Use a non-root user inside the docker container.
|
||||
Custom []string // Custom "docker run" command line options go here.
|
||||
}
|
||||
|
||||
// Ensure that Docker implements the Caller interface.
|
||||
@ -48,6 +59,8 @@ func (d Docker) args() []string {
|
||||
// Argument -i is needed for stdio to work.
|
||||
args := []string{"run", "-i"}
|
||||
|
||||
args = append(args, d.Custom...)
|
||||
|
||||
// Add mounts.
|
||||
for _, volume := range d.Volumes {
|
||||
args = append(args, "-v", volume)
|
||||
@ -120,8 +133,6 @@ func (d Docker) Fonts(options *OptionsFonts) ([]string, error) {
|
||||
func (d Docker) Compile(input io.Reader, output io.Writer, options *OptionsCompile) error {
|
||||
args := d.args()
|
||||
|
||||
// From here on come Typst arguments.
|
||||
|
||||
if options == nil {
|
||||
options = new(OptionsCompile)
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
<use xlink:href="#gCBEB678AF171DD94ACB89CCECEB5D533" x="149.22600000000003" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#gD58EEB85C3CF258DFE9908E9C6F904D4" x="154.34100000000004" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#gCBEB678AF171DD94ACB89CCECEB5D533" x="158.05900000000003" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g1E4752F03A1A865A0DBDFDB7CB983A33" x="163.17400000000004" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#gC3007A8C442F339190FF56DBF550BEA" x="163.17400000000004" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g653D6F5329F61DB2D83AF3CFD189F307" x="171.03900000000004" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g51B05C4190BD85788EF3601873C2936A" x="176.06600000000003" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g49431E85F668A3E0C612B4AA9C4D5CE8" x="182.02800000000002" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
@ -49,13 +49,13 @@
|
||||
</g>
|
||||
<g class="typst-text" transform="matrix(1 0 0 -1 14.173228346456693 35.799228346456694)">
|
||||
<use xlink:href="#gCBEB678AF171DD94ACB89CCECEB5D533" x="0" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g20CA0FB04A6BED1E0C44BC156D3D12C5" x="5.115" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g85D7D3DA5193E73F6C733369948756C2" x="5.115" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g5433311E1B7F4B245320FED5B7100250" x="10.23" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g85D7D3DA5193E73F6C733369948756C2" x="12.826" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g20CA0FB04A6BED1E0C44BC156D3D12C5" x="17.941000000000003" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g6A93160A3C7E07C6D055C9F6C1746C6A" x="12.826" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#gCBEB678AF171DD94ACB89CCECEB5D533" x="17.941000000000003" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g5433311E1B7F4B245320FED5B7100250" x="23.056000000000004" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g179D92325684FA5055722CBA7015DA1A" x="25.652000000000005" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g6A93160A3C7E07C6D055C9F6C1746C6A" x="30.767000000000003" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g6A93160A3C7E07C6D055C9F6C1746C6A" x="25.652000000000005" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#g17FCF64AFC48E81F707D872D7D9D0570" x="30.767000000000003" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
<use xlink:href="#gB119B92F4F4BA43398207C44B71084FA" x="35.882000000000005" y="0" fill="#000000" fill-rule="nonzero"/>
|
||||
</g>
|
||||
<g class="typst-text" transform="matrix(1 0 0 -1 14.173228346456693 55.68516584645669)">
|
||||
@ -222,8 +222,8 @@
|
||||
<symbol id="gCBEB678AF171DD94ACB89CCECEB5D533" overflow="visible">
|
||||
<path d="M 0 0m 3.168 1.342 v 3.817 c 0 0.65999985 0.010999918 1.3309999 0.032999992 1.474 c 0 0.05499983 -0.022000074 0.05499983 -0.065999985 0.05499983 c -0.605 -0.3739996 -1.188 -0.6489997 -2.1560001 -1.0999999 c 0.022000074 -0.12099981 0.065999985 -0.23099995 0.16500008 -0.29699993 c 0.5059999 0.20900011 0.7479999 0.2750001 0.957 0.2750001 c 0.18700004 0 0.22000003 -0.26399994 0.22000003 -0.638 v -3.586 c 0 -0.913 -0.29700017 -0.968 -1.0670002 -1.001 c -0.065999985 -0.065999985 -0.065999985 -0.297 0 -0.36299998 c 0.53900003 0.011 0.93499994 0.022 1.529 0.022 c 0.5279999 0 0.79200006 -0.011 1.342 -0.022 c 0.065999985 0.066 0.065999985 0.297 0 0.36299998 c -0.77 0.033000022 -0.957 0.088 -0.957 1.001 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g1E4752F03A1A865A0DBDFDB7CB983A33" overflow="visible">
|
||||
<path d="M 0 0m 1.584 3.773 c 0.29700005 1.0010002 1.001 2.1119998 2.4639997 2.662 c 0 0.13199997 -0.043999672 0.23099995 -0.13199997 0.28600025 c -1.1109998 -0.3300004 -1.793 -0.7920003 -2.409 -1.5070004 c -0.682 -0.7919998 -1.023 -1.7929997 -1.023 -2.6619997 c 0 -2.233 1.265 -2.673 2.112 -2.673 c 1.4410002 0 2.035 1.3970001 2.035 2.343 c 0 0.9460001 -0.50600004 1.793 -2.002 1.793 c -0.286 0 -0.7149999 -0.08799982 -1.045 -0.24199986 Z m -0.09899998 -0.3959999 c 0.36300004 0.24199986 0.72599995 0.25299978 0.913 0.25299978 c 1.0780001 0 1.3199999 -1.056 1.3199999 -1.606 c 0 -1.2099999 -0.4619999 -1.76 -1.0009999 -1.76 c -0.6930001 0 -1.32 0.374 -1.32 2.255 c 0 0.25300002 0.022000074 0.53900003 0.08800006 0.85800004 Z "/>
|
||||
<symbol id="gC3007A8C442F339190FF56DBF550BEA" overflow="visible">
|
||||
<path d="M 0 0m 1.87 5.8849998 h 1.969 c -0.85800004 -2.1339998 -1.727 -4.279 -2.475 -5.9509997 l 0.08800006 -0.07700001 l 0.748 0.033000007 c 0.62699986 1.87 1.2319999 3.6959999 2.464 6.699 l -0.17600012 0.13200045 c -0.1869998 -0.055000305 -0.4289999 -0.12100029 -0.8469999 -0.12100029 h -2.266 c -0.37399995 0 -0.352 0.11000013 -0.55 0.15400028 c -0.032999992 0 -0.04399997 0 -0.04399997 -0.032999992 c -0.011000037 -0.52800035 -0.13200003 -1.1880002 -0.22000003 -1.7600002 c 0.12099999 -0.032999992 0.231 -0.04400015 0.352 -0.032999992 c 0.24199998 0.8800001 0.605 0.9569998 0.957 0.9569998 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g51B05C4190BD85788EF3601873C2936A" overflow="visible">
|
||||
<path d="M 0 0m 2.024 3.938 c -0.065999985 -0.0769999 -0.13199997 -0.09899998 -0.13199997 0 c -0.010999918 0.29700017 -0.032999992 0.7260001 -0.08799994 0.8360002 c -0.022000074 0.05499983 -0.04400003 0.08799982 -0.13200009 0.08799982 c -0.30799997 -0.12099981 -0.594 -0.21999979 -1.3529999 -0.31900024 c -0.022000015 -0.065999985 0 -0.24199963 0.021999985 -0.3079996 c 0.594 -0.055000305 0.71500003 -0.11000013 0.71500003 -0.74800014 v -2.145 c 0 -0.902 -0.110000014 -0.946 -0.77 -1.001 c -0.066000015 -0.065999985 -0.066000015 -0.297 0 -0.36299998 c 0.32999998 0.011 0.77 0.022 1.21 0.022 c 0.43999994 0 0.77 -0.011 1.0999999 -0.022 c 0.065999985 0.066 0.065999985 0.297 0 0.36299998 c -0.5609999 0.055000007 -0.671 0.09900001 -0.671 1.001 v 1.8039999 c 0 0.23100019 0.09899998 0.36300015 0.18700004 0.46200013 c 0.41799998 0.40699983 0.9130001 0.6489999 1.342 0.6489999 c 0.22000003 0 0.45099998 -0.14300013 0.5830002 -0.3959999 c 0.10999966 -0.22000003 0.13199997 -0.5170002 0.13199997 -0.8470001 v -1.6719999 c 0 -0.902 -0.11000013 -0.946 -0.68200016 -1.001 c -0.055000067 -0.065999985 -0.055000067 -0.297 0 -0.36299998 c 0.32999992 0.011 0.68200016 0.022 1.1220002 0.022 c 0.43999958 0 0.83599997 -0.011 1.1659999 -0.022 c 0.05499983 0.066 0.05499983 0.297 0 0.36299998 c -0.6160002 0.055000007 -0.737 0.09900001 -0.737 1.001 v 1.6389999 c 0 0.605 -0.04400015 1.1329999 -0.29699993 1.474 c -0.18700027 0.2420001 -0.52800035 0.37400007 -0.9130001 0.37400007 c -0.53900003 0 -1.155 -0.14300013 -1.8040001 -0.89100003 Z "/>
|
||||
@ -231,9 +231,6 @@
|
||||
<symbol id="gD0BE2DBF7243AF20ECD6B66E738F95D2" overflow="visible">
|
||||
<path d="M 0 0m 1.87 3.938 c -0.011000037 0.33000016 -0.032999992 0.7260001 -0.08800006 0.8360002 c -0.021999955 0.05499983 -0.04399991 0.08799982 -0.13199997 0.08799982 c -0.30799997 -0.12099981 -0.594 -0.21999979 -1.3529999 -0.31900024 c -0.021999985 -0.065999985 0 -0.24199963 0.022000015 -0.3079996 c 0.594 -0.055000305 0.71500003 -0.11000013 0.71500003 -0.74800014 v -2.145 c 0 -0.902 -0.14300007 -0.957 -0.748 -1.001 c -0.066000015 -0.065999985 -0.066000015 -0.297 0 -0.36299998 c 0.32999998 0.011 0.748 0.022 1.188 0.022 c 0.44000006 0 0.7809999 -0.011 1.1110001 -0.022 c 0.065999985 0.066 0.065999985 0.297 0 0.36299998 c -0.5610001 0.055000007 -0.68200004 0.09900001 -0.68200004 1.001 v 1.8039999 c 0 0.23100019 0.0990001 0.36300015 0.18699992 0.46200013 c 0.44000006 0.42900014 0.8470001 0.6489999 1.188 0.6489999 c 0.41800022 0 0.7260003 -0.26399994 0.7260003 -1.0009999 v -1.914 c 0 -0.902 -0.0880003 -0.957 -0.68200016 -1.001 c -0.055000067 -0.065999985 -0.055000067 -0.297 0 -0.36299998 c 0.27499986 0.011 0.68200016 0.022 1.1219997 0.022 c 0.44000006 0 0.803 -0.011 1.0780001 -0.022 c 0.055000305 0.066 0.055000305 0.297 0 0.36299998 c -0.5499997 0.044 -0.6489997 0.09900001 -0.6489997 1.001 v 1.7490001 c 0 0.1539998 0 0.30799985 -0.011000156 0.43999982 c 0.5279999 0.58299994 1.0229998 0.7260001 1.4520001 0.7260001 c 0.41799974 0 0.65999985 -0.2420001 0.65999985 -0.9790001 v -1.9359999 c 0 -0.902 -0.11000013 -0.957 -0.68200016 -1.001 c -0.05499983 -0.065999985 -0.05499983 -0.297 0 -0.36299998 c 0.2750001 0.011 0.68200016 0.022 1.1220002 0.022 c 0.44000006 0 0.8250003 -0.011 1.1329999 -0.022 c 0.055000305 0.066 0.055000305 0.297 0 0.36299998 c -0.605 0.044 -0.704 0.09900001 -0.704 1.001 v 1.7379999 c 0 0.9790001 -0.16499996 1.7490001 -1.1329999 1.7490001 c -0.5609999 0 -1.243 -0.20900011 -1.815 -0.8140001 c -0.032999992 -0.032999992 -0.09899998 -0.08799982 -0.12099981 0.011000156 c -0.09899998 0.45099974 -0.52800035 0.803 -1.1000001 0.803 c -0.638 0 -1.21 -0.37400007 -1.6719999 -0.89100003 c -0.055000067 -0.055000067 -0.12100005 -0.13199997 -0.13200009 0 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g20CA0FB04A6BED1E0C44BC156D3D12C5" overflow="visible">
|
||||
<path d="M 0 0m 4.323 5.335 c 0 0.7919998 -0.61599994 1.375 -1.694 1.375 c -1.122 0 -1.8479999 -0.671 -1.8479999 -1.5180001 c 0 -0.6159997 0.29699993 -1.0669999 0.96799994 -1.4849999 l 0.28600013 -0.17600012 c -0.31900012 -0.16499996 -0.61600006 -0.36299992 -0.89100003 -0.605 c -0.45100003 -0.3959999 -0.6380001 -0.8909998 -0.6380001 -1.3199999 c 0 -1.122 0.792 -1.716 1.958 -1.716 c 1.441 0 2.1450002 1.056 2.1450002 1.892 c 0 0.63800013 -0.2750001 1.199 -0.8580003 1.551 l -0.7809999 0.47300005 c 0.51699996 0.25300002 1.3529999 0.82500005 1.3529999 1.529 Z m -1.8369999 -5.06 c -0.49500012 0 -1.243 0.341 -1.243 1.331 c 0 0.33000004 0.143 1.1000001 1.089 1.727 l 0.51699996 -0.30799985 c 0.6819999 -0.41800022 0.957 -0.9350002 0.957 -1.463 c 0 -1.1 -0.82500005 -1.2870001 -1.3199999 -1.2870001 Z m 0.08799982 6.0499997 c 0.71500015 0 0.9790001 -0.47300005 0.9790001 -0.9789996 c 0 -0.59400034 -0.58299994 -1.0890002 -0.8799999 -1.309 l -0.34100008 0.20899963 c -0.6930001 0.4510002 -0.77 0.8140001 -0.77 1.1550002 c 0 0.50600004 0.352 0.9239998 1.0119998 0.9239998 Z "/>
|
||||
</symbol>
|
||||
<symbol id="g5433311E1B7F4B245320FED5B7100250" overflow="visible">
|
||||
<path d="M 0 0m 0.77 0.65999997 c 0 -0.31899998 0.26400006 -0.58299994 0.58300006 -0.58299994 c 0.3189999 0 0.58299994 0.264 0.58299994 0.58299994 c 0 0.319 -0.26400006 0.58300006 -0.58299994 0.58300006 c -0.319 0 -0.58300006 -0.26400006 -0.58300006 -0.58300006 Z m 0 3.2779999 c 0 -0.319 0.26400006 -0.58299994 0.58300006 -0.58299994 c 0.3189999 0 0.58299994 0.26399994 0.58299994 0.58299994 c 0 0.319 -0.26400006 0.58299994 -0.58299994 0.58299994 c -0.319 0 -0.58300006 -0.26399994 -0.58300006 -0.58299994 Z "/>
|
||||
</symbol>
|
||||
|
||||
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 58 KiB |
@ -83,7 +83,7 @@ func TestREADME6(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestREADME7(t *testing.T) {
|
||||
func TestREADME8(t *testing.T) {
|
||||
markup := bytes.NewBufferString(`#set page(width: 100mm, height: auto, margin: 5mm)
|
||||
= go-typst
|
||||
|
||||
@ -110,7 +110,7 @@ A library to generate documents and reports by utilizing the command line versio
|
||||
}
|
||||
}
|
||||
|
||||
func TestREADME8(t *testing.T) {
|
||||
func TestREADME9(t *testing.T) {
|
||||
customValues := map[string]any{
|
||||
"time": time.Now(),
|
||||
"customText": "Hey there!",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user