Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions hugolib/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
// Katex is relatively slow.
PoolSize: 8,
Infof: logger.InfoCommand("wasm").Logf,
Warnf: logger.WarnCommand("wasm").Logf,
},
),
}
Expand Down
9 changes: 9 additions & 0 deletions internal/warpc/js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ export function readInput(handle) {
let currentLine = [];
const buffer = new Uint8Array(buffSize);

// These are not implemented by QuickJS.
console.warn = (value) => {
console.log(value);
};

console.error = (value) => {
throw new Error(value);
};

// Read all the available bytes
while (true) {
// Stdin file descriptor
Expand Down
4 changes: 2 additions & 2 deletions internal/warpc/js/greet.bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions internal/warpc/js/renderkatex.bundle.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions internal/warpc/js/renderkatex.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ const render = function (input) {
const expression = data.expression;
const options = data.options;
const header = input.header;
header.warnings = [];

if (options.strict == 'warn') {
// By default, KaTeX will write to console.warn, that's a little hard to handle.
options.strict = (errorCode, errorMsg) => {
header.warnings.push(
`katex: LaTeX-incompatible input and strict mode is set to 'warn': ${errorMsg} [${errorCode}]`,
);
};
}
// Any error thrown here will be caught by the common.js readInput function.
const output = katex.renderToString(expression, options);
writeOutput({ header: header, data: { output: output } });
Expand Down
13 changes: 13 additions & 0 deletions internal/warpc/warpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type Header struct {

// Set in the response if there was an error.
Err string `json:"err"`

// Warnings is a list of warnings that may be returned in the response.
Warnings []string `json:"warnings,omitempty"`
}

type Message[T any] struct {
Expand Down Expand Up @@ -155,6 +158,7 @@ func (p *dispatcherPool[Q, R]) Execute(ctx context.Context, q Message[Q]) (Messa
}

resp, err := call.response, p.Err()

if err == nil && resp.Header.Err != "" {
err = errors.New(resp.Header.Err)
}
Expand Down Expand Up @@ -270,6 +274,8 @@ type Options struct {

Infof func(format string, v ...any)

Warnf func(format string, v ...any)

// E.g. quickjs wasm. May be omitted if not needed.
Runtime Binary

Expand Down Expand Up @@ -325,6 +331,7 @@ type dispatcherPool[Q, R any] struct {
counter atomic.Uint32
dispatchers []*dispatcher[Q, R]
close func() error
opts Options

errc chan error
donec chan struct{}
Expand Down Expand Up @@ -355,6 +362,11 @@ func newDispatcher[Q, R any](opts Options) (*dispatcherPool[Q, R], error) {
// noop
}
}
if opts.Warnf == nil {
opts.Warnf = func(format string, v ...any) {
// noop
}
}

if opts.Memory <= 0 {
// 32 MiB
Expand Down Expand Up @@ -466,6 +478,7 @@ func newDispatcher[Q, R any](opts Options) (*dispatcherPool[Q, R], error) {

dp := &dispatcherPool[Q, R]{
dispatchers: make([]*dispatcher[Q, R], len(inOuts)),
opts: opts,

errc: make(chan error, 10),
donec: make(chan struct{}),
Expand Down
Binary file modified internal/warpc/wasm/greet.wasm
Binary file not shown.
Binary file modified internal/warpc/wasm/renderkatex.wasm
Binary file not shown.
37 changes: 33 additions & 4 deletions tpl/transform/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package transform
import (
"bytes"
"context"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
Expand Down Expand Up @@ -252,8 +253,16 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
return "", fmt.Errorf("invalid strict mode; expected one of error, ignore, or warn; received %s", katexInput.Options.Strict)
}

type fileCacheEntry struct {
Version string `json:"version"`
Output string `json:"output"`
Warnings []string `json:"warnings,omitempty"`
}

const fileCacheEntryVersion = "v1" // Increment on incompatible changes.

s := hashing.HashString(args...)
key := "tomath/" + s[:2] + "/" + s[2:]
key := "tomath/" + fileCacheEntryVersion + "/" + s[:2] + "/" + s[2:]
fileCache := ns.deps.ResourceSpec.FileCaches.MiscCache()

v, err := ns.cacheMath.GetOrCreate(key, func(string) (template.HTML, error) {
Expand All @@ -274,15 +283,35 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
if err != nil {
return nil, err
}
return hugio.NewReadSeekerNoOpCloserFromString(result.Data.Output), nil

e := fileCacheEntry{
Version: fileCacheEntryVersion,
Output: result.Data.Output,
Warnings: result.Header.Warnings,
}

buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
if err := enc.Encode(e); err != nil {
return nil, fmt.Errorf("failed to encode file cache entry: %w", err)
}
return hugio.NewReadSeekerNoOpCloserFromBytes(buf.Bytes()), nil
})
if err != nil {
return "", err
}

s, err := hugio.ReadString(r)
var e fileCacheEntry
if err := json.NewDecoder(r).Decode(&e); err != nil {
return "", fmt.Errorf("failed to decode file cache entry: %w", err)
}

for _, warning := range e.Warnings {
ns.deps.Log.Warnf("transform.ToMath: %s", warning)
}

return template.HTML(s), err
return template.HTML(e.Output), err
})
if err != nil {
return "", err
Expand Down
9 changes: 4 additions & 5 deletions tpl/transform/transform_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,11 +525,10 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
b.AssertFileContent("public/index.html", `<annotation encoding="application/x-tex">a %</annotation>`)

// strict: warn
// TODO: see https://github.com/gohugoio/hugo/issues/13735
// f = strings.ReplaceAll(files, "dict", `(dict "strict" "warn")`)
// b = hugolib.Test(t, f, hugolib.TestOptWarn())
// b.AssertLogMatches("[commentAtEnd]")
// b.AssertFileContent("public/index.html", `<annotation encoding="application/x-tex">a %</annotation>`)
f = strings.ReplaceAll(files, "dict", `(dict "strict" "warn")`)
b = hugolib.Test(t, f, hugolib.TestOptWarn())
b.AssertLogMatches("[commentAtEnd]")
b.AssertFileContent("public/index.html", `<annotation encoding="application/x-tex">a %</annotation>`)

// strict mode: invalid value
f = strings.ReplaceAll(files, "dict", `(dict "strict" "foo")`)
Expand Down
Loading