diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index c43456677..aef91878f 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -828,12 +828,14 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler } var dims *d2target.TextDimensions + var innerLabelPadding = 5 if obj.Attributes.Shape.Value == d2target.ShapeText { var err error dims, err = getMarkdownDimensions(mtexts, ruler, obj.Text()) if err != nil { return err } + innerLabelPadding = 0 } else { dims = getTextDimensions(mtexts, ruler, obj.Text()) } @@ -855,7 +857,6 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler } } - const innerLabelPadding = 5 dims.Width += innerLabelPadding dims.Height += innerLabelPadding obj.LabelDimensions = *dims diff --git a/d2renderers/d2svg/github-markdown.css b/d2renderers/d2svg/github-markdown.css index eae0e3009..c5adbeae5 100644 --- a/d2renderers/d2svg/github-markdown.css +++ b/d2renderers/d2svg/github-markdown.css @@ -17,7 +17,7 @@ } .md { - tab-size: 8; + tab-size: 4; } /* based on https://github.com/sindresorhus/github-markdown-css */ diff --git a/d2renderers/textmeasure/markdown.go b/d2renderers/textmeasure/markdown.go index b1ddb4b90..2f1829280 100644 --- a/d2renderers/textmeasure/markdown.go +++ b/d2renderers/textmeasure/markdown.go @@ -205,17 +205,17 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) (wid spaceRune, _ := utf8.DecodeRuneInString(" ") // measure will not include leading or trailing whitespace, so we have to add in the space width spaceWidth := ruler.atlases[font].glyph(spaceRune).advance - tabWidth := 8 * spaceWidth + tabWidth := TAB_SIZE * spaceWidth str := n.Data - htmlWhitespace := true + isCode := false switch parentElementType { case "pre", "code": - htmlWhitespace = false + isCode = true } - if htmlWhitespace { + if !isCode { str = strings.ReplaceAll(str, "\n", " ") str = strings.ReplaceAll(str, "\t", " ") if strings.HasPrefix(str, " ") { @@ -258,7 +258,13 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, font d2fonts.Font) (wid } } + if isCode { + ruler.boundsWithDot = true + } w, h := ruler.MeasurePrecise(font, str) + if isCode { + ruler.boundsWithDot = false + } // fmt.Printf("%d:'%s' width %v (%v) height %v fontStyle %s fontSize %v family %v\n", depth, n.Data, w, w+spaceWidths, h, font.Style, font.Size, font.Family) return w + spaceWidths, h, 0, 0 diff --git a/d2renderers/textmeasure/textmeasure.go b/d2renderers/textmeasure/textmeasure.go index 251e51b41..4a96c0c3a 100644 --- a/d2renderers/textmeasure/textmeasure.go +++ b/d2renderers/textmeasure/textmeasure.go @@ -14,6 +14,8 @@ import ( "oss.terrastruct.com/d2/lib/geo" ) +const TAB_SIZE = 4 + // ASCII is a set of all ASCII runes. These runes are codepoints from 32 to 127 inclusive. var ASCII []rune @@ -77,6 +79,9 @@ type Ruler struct { buf []byte prevR rune bounds *rect + + // when drawing text also union Ruler.bounds with Dot + boundsWithDot bool } // New creates a new Ruler capable of drawing runes contained in the provided atlas. Orig and Dot @@ -118,7 +123,7 @@ func NewRuler() (*Ruler, error) { atlas := NewAtlas(face, ASCII) atlases[font] = atlas lineHeights[font] = atlas.lineHeight - tabWidths[font] = atlas.glyph(' ').advance * 4 + tabWidths[font] = atlas.glyph(' ').advance * TAB_SIZE } } } @@ -199,10 +204,15 @@ func (txt *Ruler) drawBuf(font d2fonts.Font) { txt.prevR = r - if txt.bounds.w()*txt.bounds.h() == 0 { - txt.bounds = bounds - } else { + if txt.boundsWithDot { + txt.bounds = txt.bounds.union(&rect{txt.Dot, txt.Dot}) txt.bounds = txt.bounds.union(bounds) + } else { + if txt.bounds.w()*txt.bounds.h() == 0 { + txt.bounds = bounds + } else { + txt.bounds = txt.bounds.union(bounds) + } } } } diff --git a/d2renderers/textmeasure/textmeasure_test.go b/d2renderers/textmeasure/textmeasure_test.go index 8a8f53110..e7a2cb9f2 100644 --- a/d2renderers/textmeasure/textmeasure_test.go +++ b/d2renderers/textmeasure/textmeasure_test.go @@ -95,6 +95,12 @@ _italics are all measured correctly_ ` **Note:** `: {37, 24}, + `a`: {7, 24}, + `w`: {12, 24}, + `ww`: {24, 24}, + "`inline code`": {119, 27}, + "`code`": {52, 27}, + "`a`": {23, 27}, } func TestTextMeasureMarkdown(t *testing.T) { diff --git a/e2etests/testdata/todo/md_code_block_fenced/board.exp.json b/e2etests/testdata/todo/md_code_block_fenced/board.exp.json index 7040a1f5d..e23fa485a 100644 --- a/e2etests/testdata/todo/md_code_block_fenced/board.exp.json +++ b/e2etests/testdata/todo/md_code_block_fenced/board.exp.json @@ -8,8 +8,8 @@ "x": 0, "y": 226 }, - "width": 157, - "height": 130, + "width": 224, + "height": 125, "level": 1, "opacity": 1, "strokeDash": 0, @@ -35,14 +35,14 @@ "italic": false, "bold": true, "underline": false, - "labelWidth": 157, - "labelHeight": 130 + "labelWidth": 224, + "labelHeight": 125 }, { "id": "a", "type": "", "pos": { - "x": 22, + "x": 56, "y": 0 }, "width": 113, @@ -80,8 +80,8 @@ "id": "b", "type": "", "pos": { - "x": 22, - "y": 456 + "x": 56, + "y": 451 }, "width": 113, "height": 126, @@ -142,19 +142,19 @@ "labelPercentage": 0, "route": [ { - "x": 78.5, + "x": 112, "y": 126 }, { - "x": 78.5, + "x": 112, "y": 166 }, { - "x": 78.5, + "x": 112, "y": 186 }, { - "x": 78.5, + "x": 112, "y": 226 } ], @@ -189,20 +189,20 @@ "labelPercentage": 0, "route": [ { - "x": 78.5, - "y": 356 + "x": 112, + "y": 351 }, { - "x": 78.5, - "y": 396 + "x": 112, + "y": 391 }, { - "x": 78.5, - "y": 416 + "x": 112, + "y": 411 }, { - "x": 78.5, - "y": 456 + "x": 112, + "y": 451 } ], "isCurve": true, diff --git a/e2etests/testdata/todo/md_code_block_fenced/sketch.exp.svg b/e2etests/testdata/todo/md_code_block_fenced/sketch.exp.svg index b8692feab..fa200d5c7 100644 --- a/e2etests/testdata/todo/md_code_block_fenced/sketch.exp.svg +++ b/e2etests/testdata/todo/md_code_block_fenced/sketch.exp.svg @@ -2,7 +2,7 @@ \ No newline at end of file diff --git a/e2etests/testdata/todo/md_code_block_indented/board.exp.json b/e2etests/testdata/todo/md_code_block_indented/board.exp.json index d2de66634..0db1ae053 100644 --- a/e2etests/testdata/todo/md_code_block_indented/board.exp.json +++ b/e2etests/testdata/todo/md_code_block_indented/board.exp.json @@ -8,8 +8,8 @@ "x": 0, "y": 226 }, - "width": 213, - "height": 29, + "width": 208, + "height": 24, "level": 1, "opacity": 1, "strokeDash": 0, @@ -35,14 +35,14 @@ "italic": false, "bold": true, "underline": false, - "labelWidth": 213, - "labelHeight": 29 + "labelWidth": 208, + "labelHeight": 24 }, { "id": "a", "type": "", "pos": { - "x": 50, + "x": 48, "y": 0 }, "width": 113, @@ -80,8 +80,8 @@ "id": "b", "type": "", "pos": { - "x": 50, - "y": 355 + "x": 48, + "y": 350 }, "width": 113, "height": 126, @@ -142,19 +142,19 @@ "labelPercentage": 0, "route": [ { - "x": 106.5, + "x": 104, "y": 126 }, { - "x": 106.5, + "x": 104, "y": 166 }, { - "x": 106.5, + "x": 104, "y": 186 }, { - "x": 106.5, + "x": 104, "y": 226 } ], @@ -189,20 +189,20 @@ "labelPercentage": 0, "route": [ { - "x": 106.5, - "y": 255 + "x": 104, + "y": 250 }, { - "x": 106.5, - "y": 295 + "x": 104, + "y": 290 }, { - "x": 106.5, - "y": 315 + "x": 104, + "y": 310 }, { - "x": 106.5, - "y": 355 + "x": 104, + "y": 350 } ], "isCurve": true, diff --git a/e2etests/testdata/todo/md_code_block_indented/sketch.exp.svg b/e2etests/testdata/todo/md_code_block_indented/sketch.exp.svg index f0f7b544a..7a9d0b25c 100644 --- a/e2etests/testdata/todo/md_code_block_indented/sketch.exp.svg +++ b/e2etests/testdata/todo/md_code_block_indented/sketch.exp.svg @@ -2,7 +2,7 @@ \ No newline at end of file diff --git a/e2etests/todo_test.go b/e2etests/todo_test.go index b311aef33..61d2458e5 100644 --- a/e2etests/todo_test.go +++ b/e2etests/todo_test.go @@ -10,7 +10,6 @@ func testTodo(t *testing.T) { // https://github.com/terrastruct/d2/issues/24 // string monstrosity from not being able to escape backticks within string literals { - skip: false, name: "md_code_inline", script: `md: |md ` + "`code`" + ` @@ -19,7 +18,6 @@ a -> md -> b `, }, { - skip: false, name: "md_code_block_fenced", script: `md: |md ` + "```" + ` @@ -33,7 +31,6 @@ a -> md -> b `, }, { - skip: false, name: "md_code_block_indented", script: `md: |md {