Merge pull request #1191 from gavin-ts/markdown-font-size

apply font size to markdown
This commit is contained in:
gavin-ts 2023-04-12 20:37:41 -07:00 committed by GitHub
commit 60d2b0ebab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 2859 additions and 591 deletions

View file

@ -5,6 +5,8 @@
#### Improvements 🧹 #### Improvements 🧹
- Markdown text can now be adjusted with `font-size` [#1191](https://github.com/terrastruct/d2/issues/1191)
#### Bugfixes ⛑️ #### Bugfixes ⛑️
- Fixes grid layouts not applying on objects with a constant near [#1173](https://github.com/terrastruct/d2/issues/1173) - Fixes grid layouts not applying on objects with a constant near [#1173](https://github.com/terrastruct/d2/issues/1173)

View file

@ -561,7 +561,7 @@ func (obj *Object) Text() *d2target.MText {
} }
if obj.OuterSequenceDiagram() == nil { if obj.OuterSequenceDiagram() == nil {
if obj.IsContainer() { if obj.IsContainer() && obj.Attributes.Shape.Value != "text" {
fontSize = obj.Level().LabelSize() fontSize = obj.Level().LabelSize()
} }
} else { } else {
@ -1244,7 +1244,7 @@ func getMarkdownDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, t
} }
if ruler != nil { if ruler != nil {
width, height, err := textmeasure.MeasureMarkdown(t.Text, ruler, fontFamily) width, height, err := textmeasure.MeasureMarkdown(t.Text, ruler, fontFamily, t.FontSize)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -1333,6 +1333,9 @@ func drawShape(writer io.Writer, diagramHash string, targetShape d2target.Shape,
mdEl := d2themes.NewThemableElement("div") mdEl := d2themes.NewThemableElement("div")
mdEl.ClassName = "md" mdEl.ClassName = "md"
mdEl.Content = render mdEl.Content = render
if targetShape.FontSize != textmeasure.MarkdownFontSize {
mdEl.Style = fmt.Sprintf("font-size:%vpx", targetShape.FontSize)
}
fmt.Fprint(writer, mdEl.Render()) fmt.Fprint(writer, mdEl.Render())
fmt.Fprint(writer, `</foreignObject></g>`) fmt.Fprint(writer, `</foreignObject></g>`)
} else { } else {

View file

@ -883,6 +883,25 @@ ww -> ff.gg
test ~~strikethrough~~ test test ~~strikethrough~~ test
| |
x -> hey -> y
`,
},
{
name: "md_fontsize_10",
script: `hey: |md
# Every frustum longs to be a cone
- A continuing flow of paper is sufficient to continue the flow of paper
- Please remain calm, it's no use both of us being hysterical at the same time
- Visits always give pleasure: if not on arrival, then on the departure
*Festivity Level 1*: Your guests are chatting amiably with each other.
test ~~strikethrough~~ test
|
hey.style.font-size: 10
x -> hey -> y x -> hey -> y
`, `,
}, },

View file

@ -0,0 +1,269 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "hey",
"type": "text",
"pos": {
"x": 0,
"y": 166
},
"width": 332,
"height": 161,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "transparent",
"stroke": "N1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "# Every frustum longs to be a cone\n\n- A continuing flow of paper is sufficient to continue the flow of paper\n- Please remain calm, it's no use both of us being hysterical at the same time\n- Visits always give pleasure: if not on arrival, then on the departure\n\n*Festivity Level 1*: Your guests are chatting amiably with each other.\n\ntest ~~strikethrough~~ test",
"fontSize": 10,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 332,
"labelHeight": 161,
"zIndex": 0,
"level": 1
},
{
"id": "x",
"type": "rectangle",
"pos": {
"x": 140,
"y": 0
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "y",
"type": "rectangle",
"pos": {
"x": 139,
"y": 427
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 9,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(x -> hey)[0]",
"src": "x",
"srcArrow": "none",
"srcLabel": "",
"dst": "hey",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 166,
"y": 66
},
{
"x": 166,
"y": 106
},
{
"x": 166,
"y": 126
},
{
"x": 166,
"y": 166
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(hey -> y)[0]",
"src": "hey",
"srcArrow": "none",
"srcLabel": "",
"dst": "y",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 166,
"y": 327
},
{
"x": 166,
"y": 367
},
{
"x": 166,
"y": 387
},
{
"x": 166,
"y": 427
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -0,0 +1,251 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "hey",
"type": "text",
"pos": {
"x": 12,
"y": 148
},
"width": 332,
"height": 161,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "transparent",
"stroke": "N1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "# Every frustum longs to be a cone\n\n- A continuing flow of paper is sufficient to continue the flow of paper\n- Please remain calm, it's no use both of us being hysterical at the same time\n- Visits always give pleasure: if not on arrival, then on the departure\n\n*Festivity Level 1*: Your guests are chatting amiably with each other.\n\ntest ~~strikethrough~~ test",
"fontSize": 10,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 332,
"labelHeight": 161,
"zIndex": 0,
"level": 1
},
{
"id": "x",
"type": "rectangle",
"pos": {
"x": 151,
"y": 12
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "y",
"type": "rectangle",
"pos": {
"x": 151,
"y": 379
},
"width": 54,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 9,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(x -> hey)[0]",
"src": "x",
"srcArrow": "none",
"srcLabel": "",
"dst": "hey",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 178,
"y": 78
},
{
"x": 178,
"y": 148
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(hey -> y)[0]",
"src": "hey",
"srcArrow": "none",
"srcLabel": "",
"dst": "y",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 178,
"y": 309
},
{
"x": 178,
"y": 379
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -72,7 +72,7 @@
"methods": null, "methods": null,
"columns": null, "columns": null,
"label": "### company Warehouse\n- Asset Tagging\n- Inventory\n- Staging\n- Dispatch to Site", "label": "### company Warehouse\n- Asset Tagging\n- Inventory\n- Staging\n- Dispatch to Site",
"fontSize": 28, "fontSize": 16,
"fontFamily": "DEFAULT", "fontFamily": "DEFAULT",
"language": "markdown", "language": "markdown",
"color": "N1", "color": "N1",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -72,7 +72,7 @@
"methods": null, "methods": null,
"columns": null, "columns": null,
"label": "### company Warehouse\n- Asset Tagging\n- Inventory\n- Staging\n- Dispatch to Site", "label": "### company Warehouse\n- Asset Tagging\n- Inventory\n- Staging\n- Dispatch to Site",
"fontSize": 28, "fontSize": 16,
"fontFamily": "DEFAULT", "fontFamily": "DEFAULT",
"language": "markdown", "language": "markdown",
"color": "N1", "color": "N1",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -23,13 +23,13 @@ var markdownRenderer goldmark.Markdown
const ( const (
MarkdownFontSize = d2fonts.FONT_SIZE_M MarkdownFontSize = d2fonts.FONT_SIZE_M
MarkdownLineHeight = 1.5 MarkdownLineHeight = 1.5
MarkdownLineHeightPx = MarkdownFontSize * MarkdownLineHeight
PaddingLeft_ul_ol = 32 PaddingLeft_ul_ol_em = 2.
MarginBottom_ul = MarkdownFontSize MarginBottom_ul = 16.
MarginTop_li_p = MarkdownFontSize MarginTop_li_p = 16.
MarginBottom_p = MarkdownFontSize MarginTop_li_em = 0.25
MarginBottom_p = 16.
LineHeight_h = 1.25 LineHeight_h = 1.25
MarginTop_h = 24 MarginTop_h = 24
@ -37,7 +37,7 @@ const (
PaddingBottom_h1_h2_em = 0.3 PaddingBottom_h1_h2_em = 0.3
BorderBottom_h1_h2 = 1 BorderBottom_h1_h2 = 1
Height_hr = 4 Height_hr_em = 0.25
MarginTopBottom_hr = 24 MarginTopBottom_hr = 24
Padding_pre = 16 Padding_pre = 16
@ -52,21 +52,30 @@ const (
MarginBottom_blockquote = 16 MarginBottom_blockquote = 16
BorderLeft_blockquote_em = 0.25 BorderLeft_blockquote_em = 0.25
FONT_SIZE_H1 = d2fonts.FONT_SIZE_XXXL h1_em = 2.
FONT_SIZE_H2 = d2fonts.FONT_SIZE_XL h2_em = 1.5
FONT_SIZE_H3 = d2fonts.FONT_SIZE_L h3_em = 1.25
FONT_SIZE_H4 = d2fonts.FONT_SIZE_M h4_em = 1.
FONT_SIZE_H5 = d2fonts.FONT_SIZE_S h5_em = 0.875
FONT_SIZE_H6 = d2fonts.FONT_SIZE_XS h6_em = 0.85
) )
var HeaderToFontSize = map[string]int{ func HeaderToFontSize(baseFontSize int, header string) int {
"h1": FONT_SIZE_H1, switch header {
"h2": FONT_SIZE_H2, case "h1":
"h3": FONT_SIZE_H3, return int(h1_em * float64(baseFontSize))
"h4": FONT_SIZE_H4, case "h2":
"h5": FONT_SIZE_H5, return int(h2_em * float64(baseFontSize))
"h6": FONT_SIZE_H6, case "h3":
return int(h3_em * float64(baseFontSize))
case "h4":
return int(h4_em * float64(baseFontSize))
case "h5":
return int(h5_em * float64(baseFontSize))
case "h6":
return int(h6_em * float64(baseFontSize))
}
return 0
} }
func RenderMarkdown(m string) (string, error) { func RenderMarkdown(m string) (string, error) {
@ -89,7 +98,7 @@ func init() {
) )
} }
func MeasureMarkdown(mdText string, ruler *Ruler, fontFamily *d2fonts.FontFamily) (width, height int, err error) { func MeasureMarkdown(mdText string, ruler *Ruler, fontFamily *d2fonts.FontFamily, fontSize int) (width, height int, err error) {
render, err := RenderMarkdown(mdText) render, err := RenderMarkdown(mdText)
if err != nil { if err != nil {
return width, height, err return width, height, err
@ -112,7 +121,7 @@ func MeasureMarkdown(mdText string, ruler *Ruler, fontFamily *d2fonts.FontFamily
// TODO consider setting a max width + (manual) text wrapping // TODO consider setting a max width + (manual) text wrapping
bodyNode := doc.Find("body").First().Nodes[0] bodyNode := doc.Find("body").First().Nodes[0]
bodyAttrs := ruler.measureNode(0, bodyNode, fontFamily, MarkdownFontSize, d2fonts.FONT_STYLE_REGULAR) bodyAttrs := ruler.measureNode(0, bodyNode, fontFamily, fontSize, d2fonts.FONT_STYLE_REGULAR)
return int(math.Ceil(bodyAttrs.width)), int(math.Ceil(bodyAttrs.height)), nil return int(math.Ceil(bodyAttrs.width)), int(math.Ceil(bodyAttrs.height)), nil
} }
@ -272,7 +281,7 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon
isCode := false isCode := false
switch n.Data { switch n.Data {
case "h1", "h2", "h3", "h4", "h5", "h6": case "h1", "h2", "h3", "h4", "h5", "h6":
fontSize = HeaderToFontSize[n.Data] fontSize = HeaderToFontSize(fontSize, n.Data)
fontStyle = d2fonts.FONT_STYLE_SEMIBOLD fontStyle = d2fonts.FONT_STYLE_SEMIBOLD
originalLineHeight := ruler.LineHeightFactor originalLineHeight := ruler.LineHeightFactor
ruler.LineHeightFactor = LineHeight_h ruler.LineHeightFactor = LineHeight_h
@ -290,6 +299,7 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon
} }
block := blockAttrs{} block := blockAttrs{}
lineHeightPx := float64(fontSize) * ruler.LineHeightFactor
if n.FirstChild != nil { if n.FirstChild != nil {
first := getNext(n.FirstChild) first := getNext(n.FirstChild)
@ -300,8 +310,8 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon
// first create blocks from combined inline elements, then combine all blocks // first create blocks from combined inline elements, then combine all blocks
// inlineBlock will be non-nil while inline elements are being combined into a block // inlineBlock will be non-nil while inline elements are being combined into a block
endInlineBlock := func() { endInlineBlock := func() {
if !isCode && inlineBlock.height > 0 && inlineBlock.height < MarkdownLineHeightPx { if !isCode && inlineBlock.height > 0 && inlineBlock.height < lineHeightPx {
inlineBlock.height = MarkdownLineHeightPx inlineBlock.height = lineHeightPx
} }
blocks = append(blocks, *inlineBlock) blocks = append(blocks, *inlineBlock)
inlineBlock = nil inlineBlock = nil
@ -332,7 +342,7 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon
if inlineBlock != nil { if inlineBlock != nil {
endInlineBlock() endInlineBlock()
} else { } else {
block.height += MarkdownLineHeightPx block.height += lineHeightPx
} }
} else if childBlock.isNotEmpty() { } else if childBlock.isNotEmpty() {
if inlineBlock == nil { if inlineBlock == nil {
@ -391,9 +401,9 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon
block.height += PaddingBottom_h1_h2_em*float64(fontSize) + BorderBottom_h1_h2 block.height += PaddingBottom_h1_h2_em*float64(fontSize) + BorderBottom_h1_h2
} }
case "li": case "li":
block.width += PaddingLeft_ul_ol block.width += PaddingLeft_ul_ol_em * float64(fontSize)
if hasPrev(n) { if hasPrev(n) {
block.marginTop = go2.Max(block.marginTop, 4) block.marginTop = go2.Max(block.marginTop, MarginTop_li_em*float64(fontSize))
} }
case "ol", "ul": case "ol", "ul":
if hasAncestorElement(n, "ul") || hasAncestorElement(n, "ol") { if hasAncestorElement(n, "ul") || hasAncestorElement(n, "ol") {
@ -412,12 +422,12 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon
block.height += 2 * PaddingTopBottom_code_em * float64(fontSize) block.height += 2 * PaddingTopBottom_code_em * float64(fontSize)
} }
case "hr": case "hr":
block.height += Height_hr block.height += Height_hr_em * float64(fontSize)
block.marginTop = go2.Max(block.marginTop, MarginTopBottom_hr) block.marginTop = go2.Max(block.marginTop, MarginTopBottom_hr)
block.marginBottom = go2.Max(block.marginBottom, MarginTopBottom_hr) block.marginBottom = go2.Max(block.marginBottom, MarginTopBottom_hr)
} }
if block.height > 0 && block.height < MarkdownLineHeightPx { if block.height > 0 && block.height < lineHeightPx {
block.height = MarkdownLineHeightPx block.height = lineHeightPx
} }
if debugMeasure { if debugMeasure {
fmt.Printf("%s%s(%v,%v) mt:%v mb:%v\n", depthStr, n.Data, block.width, block.height, block.marginTop, block.marginBottom) fmt.Printf("%s%s(%v,%v) mt:%v mb:%v\n", depthStr, n.Data, block.width, block.height, block.marginTop, block.marginBottom)

View file

@ -110,7 +110,7 @@ func TestTextMeasureMarkdown(t *testing.T) {
} }
for text, dims := range mdTexts { for text, dims := range mdTexts {
width, height, err := textmeasure.MeasureMarkdown(text, ruler, nil) width, height, err := textmeasure.MeasureMarkdown(text, ruler, nil, textmeasure.MarkdownFontSize)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }