This commit is contained in:
Alexander Wang 2022-12-21 21:58:56 -08:00
parent 716f9d428a
commit 3a9a784342
No known key found for this signature in database
GPG key ID: D89FA31966BDBECE
6 changed files with 856 additions and 28 deletions

View file

@ -9,6 +9,7 @@ import (
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/d2themes"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
"oss.terrastruct.com/util-go/go2"
)
func Export(ctx context.Context, g *d2graph.Graph, themeID int64, fontFamily *d2fonts.FontFamily) (*d2target.Diagram, error) {
@ -16,8 +17,7 @@ func Export(ctx context.Context, g *d2graph.Graph, themeID int64, fontFamily *d2
diagram := d2target.NewDiagram()
if fontFamily == nil {
defaultFont := d2fonts.SourceSansPro
fontFamily = &defaultFont
fontFamily = go2.Pointer(d2fonts.SourceSansPro)
}
diagram.FontFamily = fontFamily

View file

@ -825,13 +825,13 @@ func findMeasured(mtexts []*d2target.MText, t1 *d2target.MText) *d2target.TextDi
return nil
}
func getMarkdownDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, t *d2target.MText) (*d2target.TextDimensions, error) {
func getMarkdownDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, t *d2target.MText, fontFamily *d2fonts.FontFamily) (*d2target.TextDimensions, error) {
if dims := findMeasured(mtexts, t); dims != nil {
return dims, nil
}
if ruler != nil {
width, height, err := textmeasure.MeasureMarkdown(t.Text, ruler)
width, height, err := textmeasure.MeasureMarkdown(t.Text, ruler, fontFamily)
if err != nil {
return nil, err
}
@ -862,8 +862,7 @@ func getTextDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, t *d2
style = d2fonts.FONT_STYLE_ITALIC
}
if fontFamily == nil {
defaultFont := d2fonts.SourceSansPro
fontFamily = &defaultFont
fontFamily = go2.Pointer(d2fonts.SourceSansPro)
}
w, h = ruler.Measure(fontFamily.Font(t.FontSize, style), t.Text)
}
@ -902,7 +901,7 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
dims = d2target.NewTextDimensions(width, height)
} else {
var err error
dims, err = getMarkdownDimensions(mtexts, ruler, obj.Text())
dims, err = getMarkdownDimensions(mtexts, ruler, obj.Text(), fontFamily)
if err != nil {
return err
}

View file

@ -45,7 +45,7 @@ func TestSketch(t *testing.T) {
`,
},
{
name: "chess",
name: "twitter",
script: `timeline mixer: "" {
explanation: |md
## **Timeline mixer**

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 649 KiB

View file

@ -66,8 +66,6 @@ var HeaderToFontSize = map[string]int{
"h6": FONT_SIZE_H6,
}
var HeaderFonts map[string]d2fonts.Font
func RenderMarkdown(m string) (string, error) {
var output bytes.Buffer
if err := markdownRenderer.Convert([]byte(m), &output); err != nil {
@ -77,11 +75,6 @@ func RenderMarkdown(m string) (string, error) {
}
func init() {
HeaderFonts = make(map[string]d2fonts.Font)
for header, fontSize := range HeaderToFontSize {
HeaderFonts[header] = d2fonts.SourceSansPro.Font(fontSize, d2fonts.FONT_STYLE_BOLD)
}
markdownRenderer = goldmark.New(
goldmark.WithRendererOptions(
goldmarkHtml.WithUnsafe(),
@ -90,7 +83,7 @@ func init() {
)
}
func MeasureMarkdown(mdText string, ruler *Ruler) (width, height int, err error) {
func MeasureMarkdown(mdText string, ruler *Ruler, fontFamily *d2fonts.FontFamily) (width, height int, err error) {
render, err := RenderMarkdown(mdText)
if err != nil {
return width, height, err
@ -111,11 +104,9 @@ func MeasureMarkdown(mdText string, ruler *Ruler) (width, height int, err error)
}()
}
font := d2fonts.SourceSansPro.Font(MarkdownFontSize, d2fonts.FONT_STYLE_REGULAR)
// TODO consider setting a max width + (manual) text wrapping
bodyNode := doc.Find("body").First().Nodes[0]
bodyAttrs := ruler.measureNode(0, bodyNode, font)
bodyAttrs := ruler.measureNode(0, bodyNode, fontFamily, MarkdownFontSize)
return int(math.Ceil(bodyAttrs.width)), int(math.Ceil(bodyAttrs.height)), nil
}
@ -201,7 +192,12 @@ func (b *blockAttrs) isNotEmpty() bool {
}
// measures node dimensions to match rendering with styles in github-markdown.css
func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) blockAttrs {
func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.FontFamily, fontSize int) blockAttrs {
if fontFamily == nil {
fontFamily = go2.Pointer(d2fonts.SourceSansPro)
}
font := fontFamily.Font(fontSize, d2fonts.FONT_STYLE_REGULAR)
var parentElementType string
if n.Parent != nil && n.Parent.Type == html.ElementNode {
parentElementType = n.Parent.Data
@ -253,7 +249,8 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) bloc
isCode := false
switch n.Data {
case "h1", "h2", "h3", "h4", "h5", "h6":
font = HeaderFonts[n.Data]
fontSize = HeaderToFontSize[n.Data]
font = fontFamily.Font(HeaderToFontSize[n.Data], d2fonts.FONT_STYLE_BOLD)
originalLineHeight := ruler.LineHeightFactor
ruler.LineHeightFactor = LineHeight_h
defer func() {
@ -264,6 +261,7 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) bloc
case "b", "strong":
font.Style = d2fonts.FONT_STYLE_BOLD
case "pre", "code":
fontFamily = go2.Pointer(d2fonts.SourceCodePro)
font.Family = d2fonts.SourceCodePro
font.Style = d2fonts.FONT_STYLE_REGULAR
isCode = true
@ -280,7 +278,7 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) bloc
// first create blocks from combined inline elements, then combine all blocks
// current will be non-nil while inline elements are being combined into a block
for child := n.FirstChild; child != nil; child = child.NextSibling {
childBlock := ruler.measureNode(depth+1, child, font)
childBlock := ruler.measureNode(depth+1, child, fontFamily, fontSize)
if child.Type == html.ElementNode && isBlockElement(child.Data) {
if current != nil {
@ -354,7 +352,7 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) bloc
switch n.Data {
case "blockquote":
block.width += (2*PaddingLR_blockquote_em + BorderLeft_blockquote_em) * float64(font.Size)
block.width += (2*PaddingLR_blockquote_em + BorderLeft_blockquote_em) * float64(fontSize)
block.marginBottom = go2.Max(block.marginBottom, MarginBottom_blockquote)
case "p":
if parentElementType == "li" {
@ -366,7 +364,7 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) bloc
block.marginBottom = go2.Max(block.marginBottom, MarginBottom_h)
switch n.Data {
case "h1", "h2":
block.height += PaddingBottom_h1_h2_em * float64(font.Size)
block.height += PaddingBottom_h1_h2_em * float64(fontSize)
}
case "li":
block.width += PaddingLeft_ul_ol
@ -386,8 +384,8 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) bloc
block.marginBottom = go2.Max(block.marginBottom, MarginBottom_pre)
case "code":
if parentElementType != "pre" {
block.width += 2 * PaddingLeftRight_code_em * float64(font.Size)
block.height += 2 * PaddingTopBottom_code_em * float64(font.Size)
block.width += 2 * PaddingLeftRight_code_em * float64(fontSize)
block.height += 2 * PaddingTopBottom_code_em * float64(fontSize)
}
case "hr":
block.height += Height_hr

10
main.go
View file

@ -14,10 +14,12 @@ import (
"github.com/spf13/pflag"
"go.uber.org/multierr"
"oss.terrastruct.com/util-go/go2"
"oss.terrastruct.com/util-go/xmain"
"oss.terrastruct.com/d2/d2lib"
"oss.terrastruct.com/d2/d2plugin"
"oss.terrastruct.com/d2/d2renderers/d2fonts"
"oss.terrastruct.com/d2/d2renderers/d2svg"
"oss.terrastruct.com/d2/d2themes"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
@ -210,11 +212,15 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, sketc
}
layout := plugin.Layout
diagram, _, err := d2lib.Compile(ctx, string(input), &d2lib.CompileOptions{
opts := &d2lib.CompileOptions{
Layout: layout,
Ruler: ruler,
ThemeID: themeID,
})
}
if sketch {
opts.FontFamily = go2.Pointer(d2fonts.HandDrawn)
}
diagram, _, err := d2lib.Compile(ctx, string(input), opts)
if err != nil {
return nil, false, err
}