d2js: add support for custom fonts
This commit is contained in:
parent
c09d29fb17
commit
a7528c40b3
5 changed files with 115 additions and 16 deletions
|
|
@ -4,17 +4,19 @@
|
||||||
|
|
||||||
#### Improvements 🧹
|
#### Improvements 🧹
|
||||||
|
|
||||||
- d2js: Support `d2-config`. Support additional options: [#2343](https://github.com/terrastruct/d2/pull/2343)
|
- d2js:
|
||||||
- `themeID`
|
- Support `d2-config`. Support additional options: [#2343](https://github.com/terrastruct/d2/pull/2343)
|
||||||
- `darkThemeID`
|
- `themeID`
|
||||||
- `center`
|
- `darkThemeID`
|
||||||
- `pad`
|
- `center`
|
||||||
- `scale`
|
- `pad`
|
||||||
- `forceAppendix`
|
- `scale`
|
||||||
- `target`
|
- `forceAppendix`
|
||||||
- `animateInterval`
|
- `target`
|
||||||
- `salt`
|
- `animateInterval`
|
||||||
- `noXMLTag`
|
- `salt`
|
||||||
|
- `noXMLTag`
|
||||||
|
- Support fonts (`fontRegular`, `fontItalic`, `fontBold`, `fontSemiBold`): (PR Pending)
|
||||||
|
|
||||||
#### Bugfixes ⛑️
|
#### Bugfixes ⛑️
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import (
|
||||||
"oss.terrastruct.com/d2/lib/textmeasure"
|
"oss.terrastruct.com/d2/lib/textmeasure"
|
||||||
"oss.terrastruct.com/d2/lib/urlenc"
|
"oss.terrastruct.com/d2/lib/urlenc"
|
||||||
"oss.terrastruct.com/d2/lib/version"
|
"oss.terrastruct.com/d2/lib/version"
|
||||||
"oss.terrastruct.com/util-go/go2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetParentID(args []js.Value) (interface{}, error) {
|
func GetParentID(args []js.Value) (interface{}, error) {
|
||||||
|
|
@ -194,6 +193,30 @@ func Compile(args []js.Value) (interface{}, error) {
|
||||||
return nil, &WASMError{Message: fmt.Sprintf("invalid fs input: %s", err.Error()), Code: 400}
|
return nil, &WASMError{Message: fmt.Sprintf("invalid fs input: %s", err.Error()), Code: 400}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fontRegular []byte
|
||||||
|
var fontItalic []byte
|
||||||
|
var fontBold []byte
|
||||||
|
var fontSemibold []byte
|
||||||
|
if input.Opts != nil && (input.Opts.FontRegular != nil) {
|
||||||
|
fontRegular = *input.Opts.FontRegular
|
||||||
|
}
|
||||||
|
if input.Opts != nil && (input.Opts.FontItalic != nil) {
|
||||||
|
fontItalic = *input.Opts.FontItalic
|
||||||
|
}
|
||||||
|
if input.Opts != nil && (input.Opts.FontBold != nil) {
|
||||||
|
fontBold = *input.Opts.FontBold
|
||||||
|
}
|
||||||
|
if input.Opts != nil && (input.Opts.FontSemibold != nil) {
|
||||||
|
fontSemibold = *input.Opts.FontSemibold
|
||||||
|
}
|
||||||
|
if fontRegular != nil || fontItalic != nil || fontBold != nil || fontSemibold != nil {
|
||||||
|
fontFamily, err := d2fonts.AddFontFamily("custom", fontRegular, fontItalic, fontBold, fontSemibold)
|
||||||
|
if err != nil {
|
||||||
|
return nil, &WASMError{Message: fmt.Sprintf("custom fonts could not be initialized: %s", err.Error()), Code: 500}
|
||||||
|
}
|
||||||
|
compileOpts.FontFamily = fontFamily
|
||||||
|
}
|
||||||
|
|
||||||
compileOpts.Ruler, err = textmeasure.NewRuler()
|
compileOpts.Ruler, err = textmeasure.NewRuler()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &WASMError{Message: fmt.Sprintf("text ruler cannot be initialized: %s", err.Error()), Code: 500}
|
return nil, &WASMError{Message: fmt.Sprintf("text ruler cannot be initialized: %s", err.Error()), Code: 500}
|
||||||
|
|
@ -206,9 +229,6 @@ func Compile(args []js.Value) (interface{}, error) {
|
||||||
renderOpts := &d2svg.RenderOpts{}
|
renderOpts := &d2svg.RenderOpts{}
|
||||||
if input.Opts != nil && input.Opts.Sketch != nil {
|
if input.Opts != nil && input.Opts.Sketch != nil {
|
||||||
renderOpts.Sketch = input.Opts.Sketch
|
renderOpts.Sketch = input.Opts.Sketch
|
||||||
if *input.Opts.Sketch {
|
|
||||||
compileOpts.FontFamily = go2.Pointer(d2fonts.HandDrawn)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if input.Opts != nil && input.Opts.Pad != nil {
|
if input.Opts != nil && input.Opts.Pad != nil {
|
||||||
renderOpts.Pad = input.Opts.Pad
|
renderOpts.Pad = input.Opts.Pad
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,11 @@ type RenderOptions struct {
|
||||||
|
|
||||||
type CompileOptions struct {
|
type CompileOptions struct {
|
||||||
RenderOptions
|
RenderOptions
|
||||||
Layout *string `json:"layout"`
|
Layout *string `json:"layout"`
|
||||||
|
FontRegular *[]byte `json:"FontRegular"`
|
||||||
|
FontItalic *[]byte `json:"FontItalic"`
|
||||||
|
FontBold *[]byte `json:"FontBold"`
|
||||||
|
FontSemibold *[]byte `json:"FontSemibold"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompileResponse struct {
|
type CompileResponse struct {
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,10 @@ Renders a compiled diagram to SVG.
|
||||||
All [RenderOptions](#renderoptions) properties in addition to:
|
All [RenderOptions](#renderoptions) properties in addition to:
|
||||||
|
|
||||||
- `layout`: Layout engine to use ('dagre' | 'elk') [default: 'dagre']
|
- `layout`: Layout engine to use ('dagre' | 'elk') [default: 'dagre']
|
||||||
|
- `fontRegular` A byte array containing .ttf file to use for the regular font. If none provided, Source Sans Pro Regular is used.
|
||||||
|
- `fontItalic` A byte array containing .ttf file to use for the italic font. If none provided, Source Sans Pro Italic is used.
|
||||||
|
- `fontBold` A byte array containing .ttf file to use for the bold font. If none provided, Source Sans Pro Bold is used.
|
||||||
|
- `fontSemibold` A byte array containing .ttf file to use for the semibold font. If none provided, Source Sans Pro Semibold is used.
|
||||||
|
|
||||||
### `RenderOptions`
|
### `RenderOptions`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,53 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="option">
|
||||||
|
<div class="option-select">
|
||||||
|
<label class="input-label">
|
||||||
|
<span>Regular Font</span>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept=".ttf"
|
||||||
|
id="font-regular-input"
|
||||||
|
class="file-input"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="option">
|
||||||
|
<div class="option-select">
|
||||||
|
<label class="input-label">
|
||||||
|
<span>Italic Font</span>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept=".ttf"
|
||||||
|
id="font-italic-input"
|
||||||
|
class="file-input"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="option">
|
||||||
|
<div class="option-select">
|
||||||
|
<label class="input-label">
|
||||||
|
<span>Bold Font</span>
|
||||||
|
<input type="file" accept=".ttf" id="font-bold-input" class="file-input" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="option">
|
||||||
|
<div class="option-select">
|
||||||
|
<label class="input-label">
|
||||||
|
<span>Semibold Font</span>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept=".ttf"
|
||||||
|
id="font-semibold-input"
|
||||||
|
class="file-input"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button onclick="compile()">Compile</button>
|
<button onclick="compile()">Compile</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -326,6 +373,12 @@
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { D2 } from "../dist/browser/index.js";
|
import { D2 } from "../dist/browser/index.js";
|
||||||
const d2 = new D2();
|
const d2 = new D2();
|
||||||
|
const loadFont = async (file) => {
|
||||||
|
if (file != undefined) {
|
||||||
|
const font = await file.arrayBuffer();
|
||||||
|
return Array.from(new Uint8Array(font));
|
||||||
|
}
|
||||||
|
};
|
||||||
window.compile = async () => {
|
window.compile = async () => {
|
||||||
const input = document.getElementById("input").value;
|
const input = document.getElementById("input").value;
|
||||||
const layout = document.getElementById("layout-toggle").checked
|
const layout = document.getElementById("layout-toggle").checked
|
||||||
|
|
@ -362,6 +415,18 @@
|
||||||
? Number(document.getElementById("animate-interval-input").value)
|
? Number(document.getElementById("animate-interval-input").value)
|
||||||
: null;
|
: null;
|
||||||
const salt = String(document.getElementById("salt-input").value);
|
const salt = String(document.getElementById("salt-input").value);
|
||||||
|
const fontRegular = await loadFont(
|
||||||
|
document.getElementById("font-regular-input").files[0]
|
||||||
|
);
|
||||||
|
const fontItalic = await loadFont(
|
||||||
|
document.getElementById("font-italic-input").files[0]
|
||||||
|
);
|
||||||
|
const fontBold = await loadFont(
|
||||||
|
document.getElementById("font-bold-input").files[0]
|
||||||
|
);
|
||||||
|
const fontSemibold = await loadFont(
|
||||||
|
document.getElementById("font-semibold-input").files[0]
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
const result = await d2.compile(input, {
|
const result = await d2.compile(input, {
|
||||||
layout,
|
layout,
|
||||||
|
|
@ -375,6 +440,10 @@
|
||||||
target,
|
target,
|
||||||
animateInterval,
|
animateInterval,
|
||||||
salt,
|
salt,
|
||||||
|
fontRegular,
|
||||||
|
fontItalic,
|
||||||
|
fontSemibold,
|
||||||
|
fontBold,
|
||||||
noXmlTag: true,
|
noXmlTag: true,
|
||||||
});
|
});
|
||||||
const svg = await d2.render(result.diagram, result.renderOptions);
|
const svg = await d2.render(result.diagram, result.renderOptions);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue