-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathrenderer.go
96 lines (82 loc) · 2.1 KB
/
renderer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package d2
import (
"bytes"
"context"
"io"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/util"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
"oss.terrastruct.com/d2/d2lib"
"oss.terrastruct.com/d2/d2renderers/d2svg"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
"oss.terrastruct.com/d2/lib/log"
"oss.terrastruct.com/d2/lib/textmeasure"
)
func ptr[T any](v T) *T {
return &v
}
type HTMLRenderer struct {
Layout d2graph.LayoutGraph
ThemeID *int64
Sketch bool
}
func (r *HTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
reg.Register(KindBlock, r.Render)
}
func (r *HTMLRenderer) Render(w util.BufWriter, src []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
n := node.(*Block)
if !entering {
w.WriteString("</div>")
return ast.WalkContinue, nil
}
w.WriteString(`<div class="d2">`)
b := bytes.Buffer{}
lines := n.Lines()
for i := 0; i < lines.Len(); i++ {
line := lines.At(i)
b.Write(line.Value(src))
}
if b.Len() == 0 {
return ast.WalkContinue, nil
}
ruler, err := textmeasure.NewRuler()
if err != nil {
return ast.WalkStop, err
}
compileOpts := &d2lib.CompileOptions{
Ruler: ruler,
LayoutResolver: func(engine string) (d2graph.LayoutGraph, error) {
if r.Layout != nil {
return r.Layout, nil
}
return d2dagrelayout.DefaultLayout, nil
},
}
renderOpts := &d2svg.RenderOpts{
Pad: ptr(int64(d2svg.DEFAULT_PADDING)),
Sketch: &r.Sketch,
}
if r.ThemeID != nil {
renderOpts.ThemeID = r.ThemeID
} else {
renderOpts.ThemeID = &d2themescatalog.CoolClassics.ID
}
ctx := context.Background()
ctx = log.With(ctx, slog.Make(sloghuman.Sink(io.Discard)))
diagram, _, err := d2lib.Compile(ctx, b.String(), compileOpts, renderOpts)
if err != nil {
_, err = w.Write(b.Bytes())
return ast.WalkContinue, err
}
out, err := d2svg.Render(diagram, renderOpts)
if err != nil {
_, err = w.Write(b.Bytes())
return ast.WalkContinue, err
}
_, err = w.Write(out)
return ast.WalkContinue, err
}