diff --git a/d2js/js/test/unit/basic.test.js b/d2js/js/test/unit/basic.test.js index 8b7bcea33..063c02b7e 100644 --- a/d2js/js/test/unit/basic.test.js +++ b/d2js/js/test/unit/basic.test.js @@ -35,6 +35,15 @@ describe("D2 Unit Tests", () => { await d2.worker.terminate(); }, 20000); + test("latex works", async () => { + const d2 = new D2(); + const result = await d2.compile("x: |latex \\frac{f(x+h)-f(x)}{h} |"); + const svg = await d2.render(result.diagram); + expect(svg).toContain(""); + await d2.worker.terminate(); + }, 20000); + test("handles syntax errors correctly", async () => { const d2 = new D2(); try { diff --git a/d2renderers/d2latex/latex.go b/d2renderers/d2latex/latex.go index a822b2c7b..2431a2f0c 100644 --- a/d2renderers/d2latex/latex.go +++ b/d2renderers/d2latex/latex.go @@ -7,8 +7,7 @@ import ( "regexp" "strconv" - "github.com/dop251/goja" - + "oss.terrastruct.com/d2/lib/jsrunner" "oss.terrastruct.com/util-go/xdefer" ) @@ -29,21 +28,24 @@ var svgRe = regexp.MustCompile(`]+width="([0-9\.]+)ex" height="([0-9\.]+) func Render(s string) (_ string, err error) { defer xdefer.Errorf(&err, "latex failed to parse") - vm := goja.New() + runner := jsrunner.NewJSRunner() - if _, err := vm.RunString(polyfillsJS); err != nil { + if _, err := runner.RunString(polyfillsJS); err != nil { return "", err } - if _, err := vm.RunString(mathjaxJS); err != nil { + if _, err := runner.RunString(mathjaxJS); err != nil { + // Known issue that a harmless error occurs in JS: https://github.com/mathjax/MathJax/issues/3289 + if runner.Engine() == jsrunner.Goja { + return "", err + } + } + + if _, err := runner.RunString(setupJS); err != nil { return "", err } - if _, err := vm.RunString(setupJS); err != nil { - return "", err - } - - val, err := vm.RunString(fmt.Sprintf(`adaptor.innerHTML(html.convert(`+"`"+"%s`"+`, { + val, err := runner.RunString(fmt.Sprintf(`adaptor.innerHTML(html.convert(`+"`"+"%s`"+`, { em: %d, ex: %d, }))`, s, pxPerEx*2, pxPerEx)) diff --git a/d2renderers/d2latex/setup.js b/d2renderers/d2latex/setup.js index c1b9c9113..d154a138f 100644 --- a/d2renderers/d2latex/setup.js +++ b/d2renderers/d2latex/setup.js @@ -4,3 +4,8 @@ const html = MathJax._.mathjax.mathjax.document('', { InputJax: new MathJax._.input.tex_ts.TeX({ packages: ['base', 'mathtools', 'ams', 'amscd', 'braket', 'cancel', 'cases', 'color', 'gensymb', 'mhchem', 'physics'] }), OutputJax: new MathJax._.output.svg_ts.SVG(), }); + +if (typeof globalThis !== 'undefined') { + globalThis.adaptor = adaptor; + globalThis.html = html; +} diff --git a/lib/jsrunner/js.go b/lib/jsrunner/js.go index 50ca70aab..18d8d54cc 100644 --- a/lib/jsrunner/js.go +++ b/lib/jsrunner/js.go @@ -42,7 +42,12 @@ func (j *jsRunner) MustGet(key string) (JSValue, error) { return &jsValue{val: result}, nil } -func (j *jsRunner) RunString(code string) (JSValue, error) { +func (j *jsRunner) RunString(code string) (_ JSValue, err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("panic: %v", r) + } + }() result := j.global.Call("eval", code) return &jsValue{val: result}, nil }