...

Source file src/oss.terrastruct.com/d2/d2renderers/d2latex/latex.go

Documentation: oss.terrastruct.com/d2/d2renderers/d2latex

     1  package d2latex
     2  
     3  import (
     4  	_ "embed"
     5  	"fmt"
     6  	"math"
     7  	"regexp"
     8  	"strconv"
     9  
    10  	"github.com/dop251/goja"
    11  
    12  	"oss.terrastruct.com/util-go/xdefer"
    13  )
    14  
    15  var pxPerEx = 8
    16  
    17  //go:embed polyfills.js
    18  var polyfillsJS string
    19  
    20  //go:embed setup.js
    21  var setupJS string
    22  
    23  //go:embed mathjax.js
    24  var mathjaxJS string
    25  
    26  // Matches this
    27  // <svg style="background: white;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="563" height="326" viewBox="-100 -100 563 326"><style type="text/css">
    28  var svgRe = regexp.MustCompile(`<svg[^>]+width="([0-9\.]+)ex" height="([0-9\.]+)ex"[^>]+>`)
    29  
    30  func Render(s string) (_ string, err error) {
    31  	defer xdefer.Errorf(&err, "latex failed to parse")
    32  	vm := goja.New()
    33  
    34  	if _, err := vm.RunString(polyfillsJS); err != nil {
    35  		return "", err
    36  	}
    37  
    38  	if _, err := vm.RunString(mathjaxJS); err != nil {
    39  		return "", err
    40  	}
    41  
    42  	if _, err := vm.RunString(setupJS); err != nil {
    43  		return "", err
    44  	}
    45  
    46  	val, err := vm.RunString(fmt.Sprintf(`adaptor.innerHTML(html.convert(`+"`"+"%s`"+`, {
    47    em: %d,
    48    ex: %d,
    49  }))`, s, pxPerEx*2, pxPerEx))
    50  	if err != nil {
    51  		return "", err
    52  	}
    53  
    54  	return val.String(), nil
    55  }
    56  
    57  func Measure(s string) (width, height int, err error) {
    58  	defer xdefer.Errorf(&err, "latex failed to parse")
    59  	svg, err := Render(s)
    60  	if err != nil {
    61  		return 0, 0, err
    62  	}
    63  
    64  	dims := svgRe.FindAllStringSubmatch(svg, -1)
    65  	if len(dims) != 1 || len(dims[0]) != 3 {
    66  		return 0, 0, fmt.Errorf("svg parsing failed for latex: %v", svg)
    67  	}
    68  
    69  	wEx := dims[0][1]
    70  	hEx := dims[0][2]
    71  
    72  	wf, err := strconv.ParseFloat(wEx, 64)
    73  	if err != nil {
    74  		return 0, 0, fmt.Errorf("svg parsing failed for latex: %v", svg)
    75  	}
    76  	hf, err := strconv.ParseFloat(hEx, 64)
    77  	if err != nil {
    78  		return 0, 0, fmt.Errorf("svg parsing failed for latex: %v", svg)
    79  	}
    80  
    81  	return int(math.Ceil(wf * float64(pxPerEx))), int(math.Ceil(hf * float64(pxPerEx))), nil
    82  }
    83  

View as plain text