diff --git a/d2exporter/export.go b/d2exporter/export.go index 96fec2ab1..73a6e37bd 100644 --- a/d2exporter/export.go +++ b/d2exporter/export.go @@ -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 diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 77f933eff..885823d16 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -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 } diff --git a/d2renderers/d2sketch/sketch_test.go b/d2renderers/d2sketch/sketch_test.go index 87b0e409a..cfcb5abdb 100644 --- a/d2renderers/d2sketch/sketch_test.go +++ b/d2renderers/d2sketch/sketch_test.go @@ -45,7 +45,7 @@ func TestSketch(t *testing.T) { `, }, { - name: "chess", + name: "twitter", script: `timeline mixer: "" { explanation: |md ## **Timeline mixer** diff --git a/d2renderers/d2sketch/testdata/twitter/sketch.exp.svg b/d2renderers/d2sketch/testdata/twitter/sketch.exp.svg new file mode 100644 index 000000000..345b29043 --- /dev/null +++ b/d2renderers/d2sketch/testdata/twitter/sketch.exp.svg @@ -0,0 +1,825 @@ + + + + + + +People discovery serviceAd mixerOnboarding serviceTwitter Frontend WebIphoneAndroidTimelineScorerHome RankerTimeline ServiceHome mixerManhattanGizmoduckSocial graphTweety PiePrediction ServiceHome ScorerManhattanMemcacheFetchFeatureScoringPrediction Service...etc

Timeline mixer

+
    +
  • Inject ads, who-to-follow, onboarding
  • +
  • Conversation module
  • +
  • Cursoring,pagination
  • +
  • Tweat deduplication
  • +
  • Served data logging
  • +
+
GraphQLFederated Strato Column

Tweet/user content hydration, visibility filtering

+
TLS-API (being deprecated)CrMixerEarlyBirdUtagSpaceCommunities iPhone webHTTP AndroidThrift RPC Candidate FetchFeature HydrationCandidate sources + + + + + + + +
\ No newline at end of file diff --git a/lib/textmeasure/markdown.go b/lib/textmeasure/markdown.go index 846c0955f..2b9f22ab2 100644 --- a/lib/textmeasure/markdown.go +++ b/lib/textmeasure/markdown.go @@ -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 diff --git a/main.go b/main.go index d4b6b63aa..45d154f1f 100644 --- a/main.go +++ b/main.go @@ -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 }