Skip to content

Commit 29cea5d

Browse files
authored
Merge pull request #2590 from alixander/customize-mono-font
customize mono font
2 parents 2f0f838 + f5b73d9 commit 29cea5d

636 files changed

Lines changed: 1051 additions & 62 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ci/release/changelogs/next.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- markdown, latex, and code can be used as edge labels [#2545](https://github.com/terrastruct/d2/pull/2545)
77
- border-x label positioning functionality [#2549](https://github.com/terrastruct/d2/pull/2549)
88
- tooltips with `near` set always show even without hover [#2564](https://github.com/terrastruct/d2/pull/2564)
9+
- CLI supports customizing monospace fonts with `--font-mono`, `--font-mono-bold`, `--font-mono-italic`, and `--font-mono-semibold` flags [#2590](https://github.com/terrastruct/d2/pull/2590)
910

1011
#### Improvements 🧹
1112

ci/release/template/man/d2.1

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,21 @@ Path to .ttf file to use for the italic font. If none provided, Source Sans Pro
105105
.It Fl -font-bold
106106
Path to .ttf file to use for the bold font. If none provided, Source Sans Pro Bold is used
107107
.Ns .
108+
.It Fl -font-semibold
109+
Path to .ttf file to use for the semibold font. If none provided, Source Sans Pro Semibold is used
110+
.Ns .
111+
.It Fl -font-mono
112+
Path to .ttf file to use for the monospace font. If none provided, Source Code Pro Regular is used
113+
.Ns .
114+
.It Fl -font-mono-bold
115+
Path to .ttf file to use for the monospace bold font. If none provided, Source Code Pro Bold is used
116+
.Ns .
117+
.It Fl -font-mono-italic
118+
Path to .ttf file to use for the monospace italic font. If none provided, Source Code Pro Italic is used
119+
.Ns .
120+
.It Fl -font-mono-semibold
121+
Path to .ttf file to use for the monospace semibold font. If none provided, Source Code Pro Semibold is used
122+
.Ns .
108123
.It Fl -pad Ar 100
109124
Pixels padded around the rendered diagram
110125
.Ns .
@@ -210,6 +225,14 @@ See --font-italic flag.
210225
See --font-bold flag.
211226
.It Ev Sy D2_FONT_SEMIBOLD
212227
See --font-semibold flag.
228+
.It Ev Sy D2_FONT_MONO
229+
See --font-mono flag.
230+
.It Ev Sy D2_FONT_MONO_BOLD
231+
See --font-mono-bold flag.
232+
.It Ev Sy D2_FONT_MONO_ITALIC
233+
See --font-mono-italic flag.
234+
.It Ev Sy D2_FONT_MONO_SEMIBOLD
235+
See --font-mono-semibold flag.
213236
.It Ev Sy D2_ANIMATE_INTERVAL
214237
See --animate-interval flag.
215238
.It Ev Sy D2_TIMEOUT

d2chaos/d2chaos_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,15 @@ func test(t *testing.T, textPath, text string) {
119119
ruler, err := textmeasure.NewRuler()
120120
assert.Nil(t, err)
121121

122-
err = g.SetDimensions(nil, ruler, nil)
122+
err = g.SetDimensions(nil, ruler, nil, nil)
123123
assert.Nil(t, err)
124124

125125
err = d2dagrelayout.DefaultLayout(ctx, g)
126126
if err != nil {
127127
t.Fatal(err)
128128
}
129129

130-
_, err = d2exporter.Export(ctx, g, nil)
130+
_, err = d2exporter.Export(ctx, g, nil, nil)
131131
if err != nil {
132132
t.Fatal(err)
133133
}

d2cli/main.go

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
125125
fontItalicFlag := ms.Opts.String("D2_FONT_ITALIC", "font-italic", "", "", "path to .ttf file to use for the italic font. If none provided, Source Sans Pro Regular-Italic is used.")
126126
fontBoldFlag := ms.Opts.String("D2_FONT_BOLD", "font-bold", "", "", "path to .ttf file to use for the bold font. If none provided, Source Sans Pro Bold is used.")
127127
fontSemiboldFlag := ms.Opts.String("D2_FONT_SEMIBOLD", "font-semibold", "", "", "path to .ttf file to use for the semibold font. If none provided, Source Sans Pro Semibold is used.")
128+
fontMonoFlag := ms.Opts.String("D2_FONT_MONO", "font-mono", "", "", "path to .ttf file to use for the monospace font. If none provided, Source Code Pro Regular is used.")
129+
fontMonoBoldFlag := ms.Opts.String("D2_FONT_MONO_BOLD", "font-mono-bold", "", "", "path to .ttf file to use for the monospace bold font. If none provided, Source Code Pro Bold is used.")
130+
fontMonoItalicFlag := ms.Opts.String("D2_FONT_MONO_ITALIC", "font-mono-italic", "", "", "path to .ttf file to use for the monospace italic font. If none provided, Source Code Pro Italic is used.")
131+
fontMonoSemiboldFlag := ms.Opts.String("D2_FONT_MONO_SEMIBOLD", "font-mono-semibold", "", "", "path to .ttf file to use for the monospace semibold font. If none provided, Source Code Pro Semibold is used.")
128132

129133
checkFlag, err := ms.Opts.Bool("D2_CHECK", "check", "", false, "check that the specified files are formatted correctly.")
130134
if err != nil {
@@ -167,7 +171,7 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
167171
return nil
168172
}
169173

170-
fontFamily, err := loadFonts(ms, *fontRegularFlag, *fontItalicFlag, *fontBoldFlag, *fontSemiboldFlag)
174+
fontFamily, monoFontFamily, err := loadFonts(ms, *fontRegularFlag, *fontItalicFlag, *fontBoldFlag, *fontSemiboldFlag, *fontMonoFlag, *fontMonoBoldFlag, *fontMonoItalicFlag, *fontMonoSemiboldFlag)
171175
if err != nil {
172176
return xmain.UsageErrorf("failed to load specified fonts: %v", err)
173177
}
@@ -366,6 +370,7 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
366370
forceAppendix: *forceAppendixFlag,
367371
pw: pw,
368372
fontFamily: fontFamily,
373+
monoFontFamily: monoFontFamily,
369374
outputFormat: outputFormat,
370375
asciiMode: *asciiModeFlag,
371376
})
@@ -398,7 +403,7 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
398403
ctx, cancel := timelib.WithTimeout(ctx, time.Minute*2)
399404
defer cancel()
400405

401-
_, written, err := compile(ctx, ms, plugins, nil, layoutFlag, renderOpts, fontFamily, *animateIntervalFlag, inputPath, outputPath, boardPath, noChildren, *bundleFlag, *forceAppendixFlag, pw.Page, outputFormat, *asciiModeFlag)
406+
_, written, err := compile(ctx, ms, plugins, nil, layoutFlag, renderOpts, fontFamily, monoFontFamily, *animateIntervalFlag, inputPath, outputPath, boardPath, noChildren, *bundleFlag, *forceAppendixFlag, pw.Page, outputFormat, *asciiModeFlag)
402407
if err != nil {
403408
if written {
404409
return fmt.Errorf("failed to fully compile (partial render written) %s: %w", ms.HumanPath(inputPath), err)
@@ -473,7 +478,7 @@ func RouterResolver(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plu
473478
}
474479
}
475480

476-
func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs fs.FS, layout *string, renderOpts d2svg.RenderOpts, fontFamily *d2fonts.FontFamily, animateInterval int64, inputPath, outputPath string, boardPath []string, noChildren, bundle, forceAppendix bool, page playwright.Page, ext exportExtension, asciiMode string) (_ []byte, written bool, _ error) {
481+
func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs fs.FS, layout *string, renderOpts d2svg.RenderOpts, fontFamily *d2fonts.FontFamily, monoFontFamily *d2fonts.FontFamily, animateInterval int64, inputPath, outputPath string, boardPath []string, noChildren, bundle, forceAppendix bool, page playwright.Page, ext exportExtension, asciiMode string) (_ []byte, written bool, _ error) {
477482
// Use ELK layout for ascii outputs when layout is dagre or unspecified
478483
if ext == TXT {
479484
if layout == nil || *layout == "dagre" {
@@ -502,6 +507,7 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs
502507
opts := &d2lib.CompileOptions{
503508
Ruler: ruler,
504509
FontFamily: fontFamily,
510+
MonoFontFamily: monoFontFamily,
505511
InputPath: inputPath,
506512
LayoutResolver: LayoutResolver(ctx, ms, plugins),
507513
Layout: layout,
@@ -1301,43 +1307,90 @@ func loadFont(ms *xmain.State, path string) ([]byte, error) {
13011307
return ttf, nil
13021308
}
13031309

1304-
func loadFonts(ms *xmain.State, pathToRegular, pathToItalic, pathToBold, pathToSemibold string) (*d2fonts.FontFamily, error) {
1305-
if pathToRegular == "" && pathToItalic == "" && pathToBold == "" && pathToSemibold == "" {
1306-
return nil, nil
1310+
func loadFonts(ms *xmain.State, pathToRegular, pathToItalic, pathToBold, pathToSemibold, pathToMono, pathToMonoBold, pathToMonoItalic, pathToMonoSemibold string) (*d2fonts.FontFamily, *d2fonts.FontFamily, error) {
1311+
if pathToRegular == "" && pathToItalic == "" && pathToBold == "" && pathToSemibold == "" &&
1312+
pathToMono == "" && pathToMonoBold == "" && pathToMonoItalic == "" && pathToMonoSemibold == "" {
1313+
return nil, nil, nil
13071314
}
13081315

13091316
var regularTTF []byte
13101317
var italicTTF []byte
13111318
var boldTTF []byte
13121319
var semiboldTTF []byte
1320+
var monoTTF []byte
1321+
var monoBoldTTF []byte
1322+
var monoItalicTTF []byte
1323+
var monoSemiboldTTF []byte
13131324

13141325
var err error
13151326
if pathToRegular != "" {
13161327
regularTTF, err = loadFont(ms, pathToRegular)
13171328
if err != nil {
1318-
return nil, err
1329+
return nil, nil, err
13191330
}
13201331
}
13211332
if pathToItalic != "" {
13221333
italicTTF, err = loadFont(ms, pathToItalic)
13231334
if err != nil {
1324-
return nil, err
1335+
return nil, nil, err
13251336
}
13261337
}
13271338
if pathToBold != "" {
13281339
boldTTF, err = loadFont(ms, pathToBold)
13291340
if err != nil {
1330-
return nil, err
1341+
return nil, nil, err
13311342
}
13321343
}
13331344
if pathToSemibold != "" {
13341345
semiboldTTF, err = loadFont(ms, pathToSemibold)
13351346
if err != nil {
1336-
return nil, err
1347+
return nil, nil, err
1348+
}
1349+
}
1350+
1351+
if pathToMono != "" {
1352+
monoTTF, err = loadFont(ms, pathToMono)
1353+
if err != nil {
1354+
return nil, nil, err
1355+
}
1356+
}
1357+
if pathToMonoBold != "" {
1358+
monoBoldTTF, err = loadFont(ms, pathToMonoBold)
1359+
if err != nil {
1360+
return nil, nil, err
1361+
}
1362+
}
1363+
if pathToMonoItalic != "" {
1364+
monoItalicTTF, err = loadFont(ms, pathToMonoItalic)
1365+
if err != nil {
1366+
return nil, nil, err
1367+
}
1368+
}
1369+
if pathToMonoSemibold != "" {
1370+
monoSemiboldTTF, err = loadFont(ms, pathToMonoSemibold)
1371+
if err != nil {
1372+
return nil, nil, err
1373+
}
1374+
}
1375+
1376+
var fontFamily *d2fonts.FontFamily
1377+
var monoFontFamily *d2fonts.FontFamily
1378+
1379+
if pathToRegular != "" || pathToItalic != "" || pathToBold != "" || pathToSemibold != "" {
1380+
fontFamily, err = d2fonts.AddFontFamily("custom", regularTTF, italicTTF, boldTTF, semiboldTTF)
1381+
if err != nil {
1382+
return nil, nil, err
1383+
}
1384+
}
1385+
1386+
if pathToMono != "" || pathToMonoBold != "" || pathToMonoItalic != "" || pathToMonoSemibold != "" {
1387+
monoFontFamily, err = d2fonts.AddFontFamily("customMono", monoTTF, monoItalicTTF, monoBoldTTF, monoSemiboldTTF)
1388+
if err != nil {
1389+
return nil, nil, err
13371390
}
13381391
}
13391392

1340-
return d2fonts.AddFontFamily("custom", regularTTF, italicTTF, boldTTF, semiboldTTF)
1393+
return fontFamily, monoFontFamily, nil
13411394
}
13421395

13431396
const LAYERS = "layers"

d2cli/watch.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type watcherOpts struct {
5757
forceAppendix bool
5858
pw png.Playwright
5959
fontFamily *d2fonts.FontFamily
60+
monoFontFamily *d2fonts.FontFamily
6061
outputFormat exportExtension
6162
asciiMode string
6263
}
@@ -443,7 +444,7 @@ func (w *watcher) compileLoop(ctx context.Context) error {
443444
if w.boardPath != "" {
444445
boardPath = strings.Split(w.boardPath, string(os.PathSeparator))
445446
}
446-
svg, _, err := compile(ctx, w.ms, w.plugins, &fs, w.layout, w.renderOpts, w.fontFamily, w.animateInterval, w.inputPath, w.outputPath, boardPath, false, w.bundle, w.forceAppendix, w.pw.Page, w.outputFormat, w.asciiMode)
447+
svg, _, err := compile(ctx, w.ms, w.plugins, &fs, w.layout, w.renderOpts, w.fontFamily, w.monoFontFamily, w.animateInterval, w.inputPath, w.outputPath, boardPath, false, w.bundle, w.forceAppendix, w.pw.Page, w.outputFormat, w.asciiMode)
447448
w.boardpathMu.Unlock()
448449
errs := ""
449450
if err != nil {

d2exporter/export.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
"oss.terrastruct.com/d2/lib/label"
2020
)
2121

22-
func Export(ctx context.Context, g *d2graph.Graph, fontFamily *d2fonts.FontFamily) (*d2target.Diagram, error) {
22+
func Export(ctx context.Context, g *d2graph.Graph, fontFamily *d2fonts.FontFamily, monoFontFamily *d2fonts.FontFamily) (*d2target.Diagram, error) {
2323
diagram := d2target.NewDiagram()
2424
applyStyles(&diagram.Root, g.Root)
2525
if g.Root.Label.MapKey == nil {
@@ -36,6 +36,11 @@ func Export(ctx context.Context, g *d2graph.Graph, fontFamily *d2fonts.FontFamil
3636
fontFamily = go2.Pointer(d2fonts.SourceCodePro)
3737
}
3838
diagram.FontFamily = fontFamily
39+
if monoFontFamily == nil {
40+
diagram.MonoFontFamily = go2.Pointer(d2fonts.SourceCodePro)
41+
} else {
42+
diagram.MonoFontFamily = monoFontFamily
43+
}
3944

4045
diagram.Shapes = make([]d2target.Shape, len(g.Objects))
4146
for i := range g.Objects {

d2exporter/export_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ func run(t *testing.T, tc testCase) {
255255
ruler, err := textmeasure.NewRuler()
256256
assert.JSON(t, nil, err)
257257

258-
err = g.SetDimensions(nil, ruler, nil)
258+
err = g.SetDimensions(nil, ruler, nil, nil)
259259
assert.JSON(t, nil, err)
260260

261261
graphInfo := d2layouts.NestedGraphInfo(g.Root)
@@ -264,7 +264,7 @@ func run(t *testing.T, tc testCase) {
264264
t.Fatal(err)
265265
}
266266

267-
got, err := d2exporter.Export(ctx, g, nil)
267+
got, err := d2exporter.Export(ctx, g, nil, nil)
268268
if err != nil {
269269
t.Fatal(err)
270270
}

0 commit comments

Comments
 (0)