markdown code tabsize and measurement accuracy

This commit is contained in:
Gavin Nishizawa 2022-11-07 18:07:04 -08:00
parent c83a55f26b
commit bffb018651
12 changed files with 158 additions and 124 deletions

View file

@ -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

View file

@ -17,7 +17,7 @@
}
.md {
tab-size: 8;
tab-size: 4;
}
/* based on https://github.com/sindresorhus/github-markdown-css */

View file

@ -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

View file

@ -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)
}
}
}
}

View file

@ -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) {

View file

@ -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,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 660 KiB

After

Width:  |  Height:  |  Size: 841 KiB

View file

@ -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,

View file

@ -2,7 +2,7 @@
<svg
style="background: white;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="413" height="681" viewBox="-100 -100 413 681"><style type="text/css">
width="408" height="676" viewBox="-100 -100 408 676"><style type="text/css">
<![CDATA[
.shape {
shape-rendering: geometricPrecision;
@ -22,6 +22,18 @@ width="413" height="681" viewBox="-100 -100 413 681"><style type="text/css">
font-family: "font-bold";
}
.md code,
.md kbd,
.md pre,
.md samp {
font-family: "font-mono";
font-size: 1em;
}
.md {
tab-size: 4;
}
/* based on https://github.com/sindresorhus/github-markdown-css */
@media (prefers-color-scheme: dark) {
.md {
@ -145,14 +157,6 @@ width="413" height="681" viewBox="-100 -100 413 681"><style type="text/css">
background-color: var(--color-canvas-default);
}
.md code,
.md kbd,
.md pre,
.md samp {
font-family: monospace, monospace;
font-size: 1em;
}
.md figure {
margin: 1em 40px;
}
@ -355,19 +359,15 @@ width="413" height="681" viewBox="-100 -100 413 681"><style type="text/css">
margin-left: 0;
}
.md tt,
/* .md tt,
.md code {
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono,
monospace;
font-size: 12px;
}
} */
.md pre {
margin-top: 0;
margin-bottom: 0;
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono,
monospace;
font-size: 12px;
/* font-size: 12px; */
word-wrap: normal;
}
@ -653,7 +653,7 @@ width="413" height="681" viewBox="-100 -100 413 681"><style type="text/css">
.md tt {
padding: 0.2em 0.4em;
margin: 0;
font-size: 85%;
/* font-size: 85%; */
background-color: var(--color-neutral-muted);
border-radius: 6px;
}
@ -693,8 +693,8 @@ width="413" height="681" viewBox="-100 -100 413 681"><style type="text/css">
.md pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
/* font-size: 85%;
line-height: 1.45; */
background-color: var(--color-canvas-subtle);
border-radius: 6px;
}
@ -797,11 +797,11 @@ width="413" height="681" viewBox="-100 -100 413 681"><style type="text/css">
.md .contains-task-list:dir(rtl) .task-list-item-checkbox {
margin: 0 -1.6em 0.25em 0.2em;
}
</style><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="0.000000" y="226.000000" width="213" height="29"><div xmlns="http://www.w3.org/1999/xhtml" class="md"><p>{
</style><g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="0.000000" y="226.000000" width="208" height="24"><div xmlns="http://www.w3.org/1999/xhtml" class="md"><p>{
indented: &quot;block&quot;,
of: &quot;json&quot;,
}</p>
</div></foreignObject></g><rect class="shape" x="50" y="0" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" /><text class="text-bold" x="106.500000" y="66.000000" style="text-anchor:middle;font-size:16px;fill:black">a</text><rect class="shape" x="50" y="355" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" /><text class="text-bold" x="106.500000" y="421.000000" style="text-anchor:middle;font-size:16px;fill:black">b</text><marker id="mk-3990223579" markerWidth="10.000000" markerHeight="12.000000" refX="8.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 106.500000 127.000000 C 106.500000 166.000000 106.500000 186.000000 106.500000 223.000000" class="connection" style="fill:none;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" marker-end="url(#mk-3990223579)" /><path d="M 106.500000 256.000000 C 106.500000 295.000000 106.500000 315.000000 106.500000 352.000000" class="connection" style="fill:none;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" marker-end="url(#mk-3990223579)" /><style type="text/css"><![CDATA[
</div></foreignObject></g><rect class="shape" x="48" y="0" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" /><text class="text-bold" x="104.500000" y="66.000000" style="text-anchor:middle;font-size:16px;fill:black">a</text><rect class="shape" x="48" y="350" width="113" height="126" style="fill:#F7F8FE;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" /><text class="text-bold" x="104.500000" y="416.000000" style="text-anchor:middle;font-size:16px;fill:black">b</text><marker id="mk-3990223579" markerWidth="10.000000" markerHeight="12.000000" refX="8.000000" refY="6.000000" viewBox="0.000000 0.000000 10.000000 12.000000" orient="auto" markerUnits="userSpaceOnUse"> <polygon class="connection" fill="#0D32B2" stroke-width="2" points="0.000000,0.000000 10.000000,6.000000 0.000000,12.000000" /> </marker><path d="M 104.000000 127.000000 C 104.000000 166.000000 104.000000 186.000000 104.000000 223.000000" class="connection" style="fill:none;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" marker-end="url(#mk-3990223579)" /><path d="M 104.000000 251.000000 C 104.000000 290.000000 104.000000 310.000000 104.000000 347.000000" class="connection" style="fill:none;stroke:#0D32B2;opacity:1.000000;stroke-width:2;" marker-end="url(#mk-3990223579)" /><style type="text/css"><![CDATA[
.text {
font-family: "font-regular";
}

Before

Width:  |  Height:  |  Size: 660 KiB

After

Width:  |  Height:  |  Size: 660 KiB

View file

@ -5,11 +5,11 @@
"id": "md",
"type": "text",
"pos": {
"x": 38,
"x": 31,
"y": 226
},
"width": 38,
"height": 29,
"width": 52,
"height": 27,
"level": 1,
"opacity": 1,
"strokeDash": 0,
@ -35,8 +35,8 @@
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 38,
"labelHeight": 29
"labelWidth": 52,
"labelHeight": 27
},
{
"id": "a",
@ -81,7 +81,7 @@
"type": "",
"pos": {
"x": 0,
"y": 355
"y": 353
},
"width": 113,
"height": 126,
@ -190,19 +190,19 @@
"route": [
{
"x": 56.5,
"y": 255
"y": 253
},
{
"x": 56.5,
"y": 295
"y": 293
},
{
"x": 56.5,
"y": 315
"y": 313
},
{
"x": 56.5,
"y": 355
"y": 353
}
],
"isCurve": true,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 660 KiB

After

Width:  |  Height:  |  Size: 841 KiB

View file

@ -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
{