@sgummalla-works/sketchon 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -4
- package/dist/adapters/assets.browser.d.ts +4 -0
- package/dist/adapters/assets.browser.d.ts.map +1 -0
- package/dist/adapters/assets.browser.js +64 -0
- package/dist/adapters/assets.browser.js.map +1 -0
- package/dist/adapters/assets.d.ts +34 -0
- package/dist/adapters/assets.d.ts.map +1 -0
- package/dist/adapters/assets.js +36 -0
- package/dist/adapters/assets.js.map +1 -0
- package/dist/adapters/assets.node.d.ts +4 -0
- package/dist/adapters/assets.node.d.ts.map +1 -0
- package/dist/adapters/assets.node.js +16 -0
- package/dist/adapters/assets.node.js.map +1 -0
- package/dist/adapters/baseline.d.ts.map +1 -1
- package/dist/adapters/baseline.js +9 -7
- package/dist/adapters/baseline.js.map +1 -1
- package/dist/adapters/elk.d.ts.map +1 -1
- package/dist/adapters/elk.js +11 -9
- package/dist/adapters/elk.js.map +1 -1
- package/dist/adapters/emoji-code.d.ts +8 -0
- package/dist/adapters/emoji-code.d.ts.map +1 -0
- package/dist/adapters/emoji-code.js +41 -0
- package/dist/adapters/emoji-code.js.map +1 -0
- package/dist/adapters/emoji.d.ts +2 -4
- package/dist/adapters/emoji.d.ts.map +1 -1
- package/dist/adapters/emoji.js +8 -34
- package/dist/adapters/emoji.js.map +1 -1
- package/dist/adapters/fonts.d.ts +3 -8
- package/dist/adapters/fonts.d.ts.map +1 -1
- package/dist/adapters/fonts.js +7 -4
- package/dist/adapters/fonts.js.map +1 -1
- package/dist/adapters/satori.d.ts.map +1 -1
- package/dist/adapters/satori.js +36 -33
- package/dist/adapters/satori.js.map +1 -1
- package/dist/adapters/sequence.d.ts.map +1 -1
- package/dist/adapters/sequence.js +19 -13
- package/dist/adapters/sequence.js.map +1 -1
- package/dist/adapters/svg.d.ts +7 -6
- package/dist/adapters/svg.d.ts.map +1 -1
- package/dist/adapters/svg.js +12 -11
- package/dist/adapters/svg.js.map +1 -1
- package/dist/composition.d.ts +54 -0
- package/dist/composition.d.ts.map +1 -0
- package/dist/composition.js +68 -0
- package/dist/composition.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +12 -0
- package/dist/constants.js.map +1 -1
- package/dist/domain/theme.d.ts +26 -0
- package/dist/domain/theme.d.ts.map +1 -1
- package/dist/domain/theme.js +52 -0
- package/dist/domain/theme.js.map +1 -1
- package/dist/index.browser.d.ts +15 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.browser.js +19 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.d.ts +13 -55
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -76
- package/dist/index.js.map +1 -1
- package/dist/ports/AssetProvider.d.ts +45 -0
- package/dist/ports/AssetProvider.d.ts.map +1 -0
- package/dist/ports/AssetProvider.js +14 -0
- package/dist/ports/AssetProvider.js.map +1 -0
- package/package.json +16 -4
package/dist/adapters/emoji.js
CHANGED
|
@@ -1,54 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Node emoji loader for Satori. Satori has no emoji font, so it calls
|
|
3
3
|
* `loadAdditionalAsset('emoji', segment)` for each emoji grapheme and expects an
|
|
4
4
|
* image data-URI back. We map the emoji to a Twemoji SVG (jdecked's maintained
|
|
5
5
|
* fork), cache it to `assets/emoji/` so the lab runs offline after the first
|
|
6
6
|
* fetch, and return it base64-encoded.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* name won't match (e.g. ⚙️ U+2699 U+FE0F → "2699.svg").
|
|
8
|
+
* Browser counterpart: `assets.browser.ts` (fetch + in-memory cache, no disk).
|
|
9
|
+
* Codepoint derivation is shared via `emoji-code.ts`.
|
|
11
10
|
*/
|
|
12
11
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
13
12
|
import { dirname, resolve } from 'node:path';
|
|
14
13
|
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { TWEMOJI_SVG_CDN_BASE } from '../constants.js';
|
|
15
|
+
import { emojiCode } from './emoji-code.js';
|
|
15
16
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
17
|
const EMOJI_DIR = resolve(__dirname, '../../assets/emoji');
|
|
17
|
-
const TWEMOJI_BASE = 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg';
|
|
18
|
-
const U200D = String.fromCharCode(0x200d); // zero-width joiner
|
|
19
|
-
const UFE0F = /️/g; // variation selector-16
|
|
20
18
|
/** A 1×1 transparent SVG, returned when an emoji can't be resolved (offline / 404). */
|
|
21
19
|
const TRANSPARENT = `data:image/svg+xml;base64,${Buffer.from('<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>').toString('base64')}`;
|
|
22
|
-
/** Convert a (possibly surrogate-pair) string to dash-joined hex codepoints. */
|
|
23
|
-
function toCodePoint(s) {
|
|
24
|
-
const out = [];
|
|
25
|
-
let prev = 0;
|
|
26
|
-
for (let i = 0; i < s.length; i++) {
|
|
27
|
-
const c = s.charCodeAt(i);
|
|
28
|
-
if (prev) {
|
|
29
|
-
out.push((0x10000 + ((prev - 0xd800) << 10) + (c - 0xdc00)).toString(16));
|
|
30
|
-
prev = 0;
|
|
31
|
-
}
|
|
32
|
-
else if (c >= 0xd800 && c <= 0xdbff) {
|
|
33
|
-
prev = c;
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
out.push(c.toString(16));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return out.join('-');
|
|
40
|
-
}
|
|
41
|
-
/** Twemoji asset code for an emoji grapheme (FE0F stripped unless ZWJ-joined). */
|
|
42
|
-
export function emojiCode(emoji) {
|
|
43
|
-
const grapheme = emoji.indexOf(U200D) < 0 ? emoji.replace(UFE0F, '') : emoji;
|
|
44
|
-
return toCodePoint(grapheme);
|
|
45
|
-
}
|
|
46
20
|
const memCache = new Map(); // code -> data URI
|
|
47
21
|
/**
|
|
48
22
|
* Resolve an emoji to a base64 SVG data-URI for Satori, via disk + memory cache.
|
|
49
23
|
*
|
|
50
|
-
* @param emoji a single emoji grapheme
|
|
51
|
-
* @returns a data-URI for the Twemoji SVG, or a transparent pixel if unresolved
|
|
24
|
+
* @param emoji a single emoji grapheme.
|
|
25
|
+
* @returns a data-URI for the Twemoji SVG, or a transparent pixel if unresolved.
|
|
52
26
|
*/
|
|
53
27
|
export async function emojiToDataUri(emoji) {
|
|
54
28
|
const code = emojiCode(emoji);
|
|
@@ -63,7 +37,7 @@ export async function emojiToDataUri(emoji) {
|
|
|
63
37
|
}
|
|
64
38
|
else {
|
|
65
39
|
try {
|
|
66
|
-
const res = await fetch(`${
|
|
40
|
+
const res = await fetch(`${TWEMOJI_SVG_CDN_BASE}/${code}.svg`);
|
|
67
41
|
if (res.ok) {
|
|
68
42
|
svg = await res.text();
|
|
69
43
|
writeFileSync(file, svg, 'utf8');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emoji.js","sourceRoot":"","sources":["../../src/adapters/emoji.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"emoji.js","sourceRoot":"","sources":["../../src/adapters/emoji.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AAE3D,uFAAuF;AACvF,MAAM,WAAW,GAAG,6BAA6B,MAAM,CAAC,IAAI,CAC1D,gEAAgE,CACjE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;AAEvB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,mBAAmB;AAE/D;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa;IAChD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,EAAE,GAAG,IAAI,MAAM,CAAC,CAAC;IAC/C,IAAI,GAAuB,CAAC;IAE5B,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACrB,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,oBAAoB,IAAI,IAAI,MAAM,CAAC,CAAC;YAC/D,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACX,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;gBACvB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;QACzE,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,6BAA6B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;IACnG,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACxB,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/adapters/fonts.d.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
name: string;
|
|
3
|
-
data: Buffer;
|
|
4
|
-
weight: 400 | 600 | 700;
|
|
5
|
-
style: 'normal';
|
|
6
|
-
}
|
|
1
|
+
import type { SketchonFont } from '../ports/AssetProvider.js';
|
|
7
2
|
/**
|
|
8
3
|
* Load the Inter font set (regular / semibold / bold) for Satori.
|
|
9
4
|
*
|
|
10
|
-
* @returns the font descriptors Satori expects in its `fonts` option
|
|
5
|
+
* @returns the font descriptors Satori expects in its `fonts` option.
|
|
11
6
|
*/
|
|
12
|
-
export declare function loadFonts():
|
|
7
|
+
export declare function loadFonts(): SketchonFont[];
|
|
13
8
|
//# sourceMappingURL=fonts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/adapters/fonts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/adapters/fonts.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAO9D;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,YAAY,EAAE,CAQ1C"}
|
package/dist/adapters/fonts.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* system font access). We bundle Inter TTFs (OFL-licensed) under assets
|
|
4
|
-
* lab is self-contained and runs offline after clone. Loaded once
|
|
2
|
+
* Node font loader for Satori. Satori needs at least one font buffer (it has no
|
|
3
|
+
* system font access). We bundle Inter TTFs (OFL-licensed) under `assets/` so
|
|
4
|
+
* the lab is self-contained and runs offline after clone. Loaded once, cached.
|
|
5
|
+
*
|
|
6
|
+
* Browser counterpart: `assets.browser.ts` (fetches the same weights from a
|
|
7
|
+
* CDN, since a browser has no disk).
|
|
5
8
|
*/
|
|
6
9
|
import { readFileSync } from 'node:fs';
|
|
7
10
|
import { dirname, resolve } from 'node:path';
|
|
@@ -12,7 +15,7 @@ let cached = null;
|
|
|
12
15
|
/**
|
|
13
16
|
* Load the Inter font set (regular / semibold / bold) for Satori.
|
|
14
17
|
*
|
|
15
|
-
* @returns the font descriptors Satori expects in its `fonts` option
|
|
18
|
+
* @returns the font descriptors Satori expects in its `fonts` option.
|
|
16
19
|
*/
|
|
17
20
|
export function loadFonts() {
|
|
18
21
|
if (cached)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/adapters/fonts.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/adapters/fonts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;AAElD,IAAI,MAAM,GAA0B,IAAI,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,GAAG;QACP,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE;QACrG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE;QACrG,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE;KACtG,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"satori.d.ts","sourceRoot":"","sources":["../../src/adapters/satori.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"satori.d.ts","sourceRoot":"","sources":["../../src/adapters/satori.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAkRrE,eAAO,MAAM,eAAe,EAAE,SAsC7B,CAAC"}
|
package/dist/adapters/satori.js
CHANGED
|
@@ -16,18 +16,19 @@
|
|
|
16
16
|
* overlap) — fidelity + the visual gallery are the real signal here.
|
|
17
17
|
*/
|
|
18
18
|
import satori from 'satori';
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
19
|
+
import { resolveTheme } from '../domain/theme.js';
|
|
20
|
+
import { getAssetProvider } from './assets.js';
|
|
21
|
+
import { CHECKPOINT_COLORS, el, monogram, stripEmoji, } from './satori-helpers.js';
|
|
22
22
|
/**
|
|
23
23
|
* Render a node's leading glyph. If the node carries an emoji `icon`, emit it as
|
|
24
24
|
* text at `size` — Satori turns it into a Twemoji image via loadAdditionalAsset.
|
|
25
25
|
* Otherwise fall back to a tinted monogram chip so iconless cards still read.
|
|
26
26
|
*/
|
|
27
|
-
function iconEl(node, size,
|
|
27
|
+
function iconEl(node, size, theme, textColor) {
|
|
28
28
|
if (node.icon) {
|
|
29
29
|
return el('div', { display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: size }, node.icon);
|
|
30
30
|
}
|
|
31
|
+
// Monogram fallback — a subtle translucent chip behind the mono text colour.
|
|
31
32
|
return el('div', {
|
|
32
33
|
display: 'flex',
|
|
33
34
|
alignItems: 'center',
|
|
@@ -35,8 +36,8 @@ function iconEl(node, size, onCard) {
|
|
|
35
36
|
width: 32,
|
|
36
37
|
height: 32,
|
|
37
38
|
borderRadius: 8,
|
|
38
|
-
background:
|
|
39
|
-
color:
|
|
39
|
+
background: theme.mode === 'dark' ? 'rgba(255,255,255,0.15)' : 'rgba(15,23,42,0.08)',
|
|
40
|
+
color: textColor,
|
|
40
41
|
fontSize: 15,
|
|
41
42
|
fontWeight: 700,
|
|
42
43
|
}, monogram(node.label));
|
|
@@ -53,7 +54,6 @@ const HEADER_H = 34;
|
|
|
53
54
|
const LEGEND_H = 52;
|
|
54
55
|
const ARROW_W = 10; // connector arrowhead width
|
|
55
56
|
const ARROW_H = 7; // connector arrowhead height
|
|
56
|
-
const CONNECTOR_COLOR = '#cbd5e1';
|
|
57
57
|
const TITLE_H = 40;
|
|
58
58
|
/** Map a node to its fill colour via category → emphasis → palette. */
|
|
59
59
|
function nodeEmphasis(spec, node) {
|
|
@@ -70,8 +70,8 @@ function subline(node) {
|
|
|
70
70
|
return node.sublabelParts.map(stripEmoji).join(' · ');
|
|
71
71
|
return node.sublabel ? stripEmoji(node.sublabel) : '';
|
|
72
72
|
}
|
|
73
|
-
function cardEl(spec, node) {
|
|
74
|
-
const
|
|
73
|
+
function cardEl(spec, node, theme) {
|
|
74
|
+
const p = theme.palette[nodeEmphasis(spec, node)];
|
|
75
75
|
const sub = subline(node);
|
|
76
76
|
return el('div', {
|
|
77
77
|
display: 'flex',
|
|
@@ -82,14 +82,13 @@ function cardEl(spec, node) {
|
|
|
82
82
|
height: CARD_H,
|
|
83
83
|
padding: '0 18px',
|
|
84
84
|
borderRadius: 12,
|
|
85
|
-
background: fill,
|
|
85
|
+
background: p.fill,
|
|
86
|
+
border: `1px solid ${p.stroke}`,
|
|
86
87
|
}, [
|
|
87
|
-
iconEl(node, 28,
|
|
88
|
+
iconEl(node, 28, theme, p.text),
|
|
88
89
|
el('div', { display: 'flex', flexDirection: 'column', gap: 2 }, [
|
|
89
|
-
el('div', { color:
|
|
90
|
-
sub
|
|
91
|
-
? el('div', { color: 'rgba(255,255,255,0.82)', fontSize: 12, fontWeight: 400 }, sub)
|
|
92
|
-
: null,
|
|
90
|
+
el('div', { color: p.text, fontSize: 16, fontWeight: 700 }, stripEmoji(node.label)),
|
|
91
|
+
sub ? el('div', { color: p.text, opacity: 0.78, fontSize: 12, fontWeight: 400 }, sub) : null,
|
|
93
92
|
]),
|
|
94
93
|
]);
|
|
95
94
|
}
|
|
@@ -121,7 +120,7 @@ function checkpointEl(node) {
|
|
|
121
120
|
* and a coloured top border) — pure flexbox, no coordinates, matches the
|
|
122
121
|
* reference's arrowed connectors.
|
|
123
122
|
*/
|
|
124
|
-
function connectorEl() {
|
|
123
|
+
function connectorEl(theme) {
|
|
125
124
|
const stem = CONNECTOR_H - ARROW_H - 2;
|
|
126
125
|
return el('div', {
|
|
127
126
|
display: 'flex',
|
|
@@ -131,17 +130,17 @@ function connectorEl() {
|
|
|
131
130
|
alignItems: 'center',
|
|
132
131
|
justifyContent: 'center',
|
|
133
132
|
}, [
|
|
134
|
-
el('div', { width: 2, height: stem, background:
|
|
133
|
+
el('div', { width: 2, height: stem, background: theme.connector }, undefined),
|
|
135
134
|
el('div', {
|
|
136
135
|
width: 0,
|
|
137
136
|
height: 0,
|
|
138
137
|
borderLeft: `${ARROW_W / 2}px solid transparent`,
|
|
139
138
|
borderRight: `${ARROW_W / 2}px solid transparent`,
|
|
140
|
-
borderTop: `${ARROW_H}px solid ${
|
|
139
|
+
borderTop: `${ARROW_H}px solid ${theme.connector}`,
|
|
141
140
|
}, undefined),
|
|
142
141
|
]);
|
|
143
142
|
}
|
|
144
|
-
function buildTree(spec) {
|
|
143
|
+
function buildTree(spec, theme) {
|
|
145
144
|
const annByTarget = new Map();
|
|
146
145
|
for (const a of spec.annotations ?? []) {
|
|
147
146
|
if (a.target)
|
|
@@ -151,11 +150,11 @@ function buildTree(spec) {
|
|
|
151
150
|
spec.nodes.forEach((node, idx) => {
|
|
152
151
|
if (idx > 0) {
|
|
153
152
|
bodyRows.push(el('div', { display: 'flex', flexDirection: 'row', width: '100%' }, [
|
|
154
|
-
connectorEl(),
|
|
153
|
+
connectorEl(theme),
|
|
155
154
|
el('div', { display: 'flex', flex: 1 }, undefined),
|
|
156
155
|
]));
|
|
157
156
|
}
|
|
158
|
-
const left = node.shape === 'checkpoint' ? checkpointEl(node) : cardEl(spec, node);
|
|
157
|
+
const left = node.shape === 'checkpoint' ? checkpointEl(node) : cardEl(spec, node, theme);
|
|
159
158
|
const ann = annByTarget.get(node.id);
|
|
160
159
|
bodyRows.push(el('div', { display: 'flex', flexDirection: 'row', width: '100%', alignItems: 'center' }, [
|
|
161
160
|
el('div', { display: 'flex', width: LEFT_W }, [left]),
|
|
@@ -163,7 +162,7 @@ function buildTree(spec) {
|
|
|
163
162
|
display: 'flex',
|
|
164
163
|
flex: 1,
|
|
165
164
|
paddingLeft: GAP_COL,
|
|
166
|
-
color:
|
|
165
|
+
color: theme.textMuted,
|
|
167
166
|
fontSize: 14,
|
|
168
167
|
fontWeight: 400,
|
|
169
168
|
alignItems: 'center',
|
|
@@ -172,7 +171,7 @@ function buildTree(spec) {
|
|
|
172
171
|
});
|
|
173
172
|
const children = [];
|
|
174
173
|
if (spec.title) {
|
|
175
|
-
children.push(el('div', { display: 'flex', color:
|
|
174
|
+
children.push(el('div', { display: 'flex', color: theme.textPrimary, fontSize: 18, fontWeight: 700, height: TITLE_H }, stripEmoji(spec.title)));
|
|
176
175
|
}
|
|
177
176
|
if (spec.columns) {
|
|
178
177
|
children.push(el('div', {
|
|
@@ -181,18 +180,18 @@ function buildTree(spec) {
|
|
|
181
180
|
width: '100%',
|
|
182
181
|
height: HEADER_H,
|
|
183
182
|
alignItems: 'center',
|
|
184
|
-
borderBottom:
|
|
183
|
+
borderBottom: `1px solid ${theme.borderLight}`,
|
|
185
184
|
marginBottom: 6,
|
|
186
185
|
}, [
|
|
187
|
-
el('div', { display: 'flex', width: LEFT_W, color:
|
|
188
|
-
el('div', { display: 'flex', flex: 1, paddingLeft: GAP_COL, color:
|
|
186
|
+
el('div', { display: 'flex', width: LEFT_W, color: theme.textMuted, fontSize: 13, fontWeight: 600 }, spec.columns.primary),
|
|
187
|
+
el('div', { display: 'flex', flex: 1, paddingLeft: GAP_COL, color: theme.textMuted, fontSize: 13, fontWeight: 600 }, spec.columns.annotation),
|
|
189
188
|
]));
|
|
190
189
|
}
|
|
191
190
|
children.push(el('div', { display: 'flex', flexDirection: 'column', width: '100%' }, bodyRows));
|
|
192
191
|
if (spec.categories?.length) {
|
|
193
192
|
const items = spec.categories.map((c) => el('div', { display: 'flex', flexDirection: 'row', alignItems: 'center', gap: 8, marginRight: 22 }, [
|
|
194
|
-
el('div', { width: 14, height: 14, borderRadius: 4, background:
|
|
195
|
-
el('div', { display: 'flex', color:
|
|
193
|
+
el('div', { width: 14, height: 14, borderRadius: 4, background: theme.palette[c.emphasis ?? 'normal'].fill }, undefined),
|
|
194
|
+
el('div', { display: 'flex', color: theme.textBody, fontSize: 13 }, c.label),
|
|
196
195
|
]));
|
|
197
196
|
children.push(el('div', {
|
|
198
197
|
display: 'flex',
|
|
@@ -202,7 +201,7 @@ function buildTree(spec) {
|
|
|
202
201
|
height: LEGEND_H,
|
|
203
202
|
alignItems: 'center',
|
|
204
203
|
marginTop: 8,
|
|
205
|
-
borderTop:
|
|
204
|
+
borderTop: `1px solid ${theme.borderLight}`,
|
|
206
205
|
paddingTop: 12,
|
|
207
206
|
}, items));
|
|
208
207
|
}
|
|
@@ -212,7 +211,7 @@ function buildTree(spec) {
|
|
|
212
211
|
width: '100%',
|
|
213
212
|
height: '100%',
|
|
214
213
|
padding: PAD,
|
|
215
|
-
background:
|
|
214
|
+
background: theme.bg,
|
|
216
215
|
}, children);
|
|
217
216
|
}
|
|
218
217
|
/** Estimate container height from row counts (container-level math, not per-node placement). */
|
|
@@ -236,9 +235,13 @@ export const satoriTechnique = {
|
|
|
236
235
|
name: 'Satori (flexbox → SVG)',
|
|
237
236
|
blurb: 'Model declares structure; Satori computes every pixel via flexbox. Primary engine for cards/columns/legend.',
|
|
238
237
|
async render(spec) {
|
|
239
|
-
|
|
238
|
+
// Fonts + emoji come from the environment-bound AssetProvider (disk in Node,
|
|
239
|
+
// fetch in the browser), overridable by the consumer via configureAssets().
|
|
240
|
+
const assets = getAssetProvider();
|
|
241
|
+
const fonts = await assets.loadFonts();
|
|
242
|
+
const theme = resolveTheme(spec.theme?.mode);
|
|
240
243
|
const height = estimateHeight(spec);
|
|
241
|
-
const tree = buildTree(spec);
|
|
244
|
+
const tree = buildTree(spec, theme);
|
|
242
245
|
const svg = await satori(tree, {
|
|
243
246
|
width: WIDTH,
|
|
244
247
|
height,
|
|
@@ -246,7 +249,7 @@ export const satoriTechnique = {
|
|
|
246
249
|
// Satori has no emoji font; resolve each emoji grapheme to a Twemoji SVG.
|
|
247
250
|
loadAdditionalAsset: async (code, segment) => {
|
|
248
251
|
if (code === 'emoji')
|
|
249
|
-
return emojiToDataUri(segment);
|
|
252
|
+
return assets.emojiToDataUri(segment);
|
|
250
253
|
return '';
|
|
251
254
|
},
|
|
252
255
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"satori.js","sourceRoot":"","sources":["../../src/adapters/satori.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"satori.js","sourceRoot":"","sources":["../../src/adapters/satori.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../../src/adapters/sequence.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../../src/adapters/sequence.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAsDrE,eAAO,MAAM,iBAAiB,EAAE,SA8G/B,CAAC"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Labels never overlap because each message occupies a unique Y row.
|
|
8
8
|
*/
|
|
9
9
|
import { NODE_LABEL_FONT_SIZE, EDGE_LABEL_FONT_SIZE, } from '../constants.js';
|
|
10
|
-
import { DARK_PRIMARY, DARK_ACCENT, DARK_SUCCESS, DARK_DANGER, DARK_NORMAL, DARK_MUTED, ACTOR_CYCLE_FILLS,
|
|
10
|
+
import { DARK_PRIMARY, DARK_ACCENT, DARK_SUCCESS, DARK_DANGER, DARK_NORMAL, DARK_MUTED, ACTOR_CYCLE_FILLS, resolveTheme, } from '../domain/theme.js';
|
|
11
11
|
import { esc, svgDocument } from './svg.js';
|
|
12
12
|
// ── Layout constants ──────────────────────────────────────────────────────────
|
|
13
13
|
const ACTOR_COL_W = 210;
|
|
@@ -23,6 +23,11 @@ const FIRST_MSG_OFFSET = 52;
|
|
|
23
23
|
const MSG_STEP = 52;
|
|
24
24
|
const ARROW_SIZE = 8;
|
|
25
25
|
const SELF_LOOP_W = 44;
|
|
26
|
+
const TITLE_FONT_SIZE = 17;
|
|
27
|
+
// Baseline the title low enough that its glyph tops stay inside the canvas: a
|
|
28
|
+
// 17px face rises ~13px above the baseline, so the old `ACTOR_Y_PAD - 2` (=8)
|
|
29
|
+
// clipped the title at the top edge (caught by the FE browser legibility e2e).
|
|
30
|
+
const TITLE_BASELINE_Y = ACTOR_Y_PAD + TITLE_FONT_SIZE - 3;
|
|
26
31
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
32
|
const EMPHASIS_DARK = {
|
|
28
33
|
primary: DARK_PRIMARY,
|
|
@@ -43,12 +48,12 @@ function actorCx(i) {
|
|
|
43
48
|
function messageY(actorBoxBottom, rowIndex) {
|
|
44
49
|
return actorBoxBottom + FIRST_MSG_OFFSET + rowIndex * MSG_STEP;
|
|
45
50
|
}
|
|
46
|
-
function arrowhead(x1, x2, y, isDashed) {
|
|
51
|
+
function arrowhead(x1, x2, y, isDashed, theme) {
|
|
47
52
|
const dir = x2 >= x1 ? 1 : -1;
|
|
48
53
|
const tip = x2;
|
|
49
54
|
const base = tip - dir * ARROW_SIZE;
|
|
50
55
|
const half = ARROW_SIZE * 0.5;
|
|
51
|
-
const fill = isDashed ?
|
|
56
|
+
const fill = isDashed ? theme.edgeDashed : theme.edgeDefault;
|
|
52
57
|
return `<polygon points="${tip},${y} ${base},${y - half} ${base},${y + half}" fill="${fill}"/>`;
|
|
53
58
|
}
|
|
54
59
|
export const sequenceTechnique = {
|
|
@@ -56,6 +61,7 @@ export const sequenceTechnique = {
|
|
|
56
61
|
name: 'Sequence (lifeline)',
|
|
57
62
|
blurb: 'Actor columns + message rows — proper lifeline diagram, no ELK.',
|
|
58
63
|
render(spec) {
|
|
64
|
+
const theme = resolveTheme(spec.theme?.mode);
|
|
59
65
|
const nodes = spec.nodes;
|
|
60
66
|
const edges = spec.edges;
|
|
61
67
|
const n = nodes.length;
|
|
@@ -69,14 +75,14 @@ export const sequenceTechnique = {
|
|
|
69
75
|
const colOf = new Map(nodes.map((nd, i) => [nd.id, i]));
|
|
70
76
|
const parts = [];
|
|
71
77
|
if (spec.title) {
|
|
72
|
-
parts.push(`<text x="${CANVAS_PAD_X}" y="${
|
|
73
|
-
`font-size="
|
|
78
|
+
parts.push(`<text x="${CANVAS_PAD_X}" y="${TITLE_BASELINE_Y}" ` +
|
|
79
|
+
`font-size="${TITLE_FONT_SIZE}" font-weight="700" fill="${theme.textPrimary}">${esc(spec.title)}</text>`);
|
|
74
80
|
}
|
|
75
81
|
nodes.forEach((_, i) => {
|
|
76
82
|
const cx = actorCx(i);
|
|
77
83
|
parts.push(`<line x1="${cx.toFixed(1)}" y1="${lifelineTop}" ` +
|
|
78
84
|
`x2="${cx.toFixed(1)}" y2="${lifelineBottom}" ` +
|
|
79
|
-
`stroke="${
|
|
85
|
+
`stroke="${theme.borderDefault}" stroke-width="1.5" stroke-dasharray="6 4"/>`);
|
|
80
86
|
});
|
|
81
87
|
nodes.forEach((node, i) => {
|
|
82
88
|
const cx = actorCx(i);
|
|
@@ -86,7 +92,7 @@ export const sequenceTechnique = {
|
|
|
86
92
|
parts.push(`<rect x="${bx.toFixed(1)}" y="${actorBoxTop}" ` +
|
|
87
93
|
`width="${ACTOR_BOX_W}" height="${ACTOR_BOX_H}" ` +
|
|
88
94
|
`rx="${ACTOR_BOX_RX}" fill="${fill}" stroke="none"/>`, `<text x="${cx.toFixed(1)}" y="${cy.toFixed(1)}" ` +
|
|
89
|
-
`font-size="${NODE_LABEL_FONT_SIZE}" font-weight="600" fill="${
|
|
95
|
+
`font-size="${NODE_LABEL_FONT_SIZE}" font-weight="600" fill="${theme.textWhite}" ` +
|
|
90
96
|
`text-anchor="middle" dominant-baseline="middle">${esc(node.label)}</text>`);
|
|
91
97
|
});
|
|
92
98
|
edges.forEach((edge, rowIdx) => {
|
|
@@ -95,17 +101,17 @@ export const sequenceTechnique = {
|
|
|
95
101
|
const y = messageY(actorBoxBottom, rowIdx);
|
|
96
102
|
const isDashed = edge.style === 'dashed' || edge.style === 'dotted' ||
|
|
97
103
|
edge.semantic === 'return';
|
|
98
|
-
const stroke = isDashed ?
|
|
104
|
+
const stroke = isDashed ? theme.edgeDashed : theme.edgeDefault;
|
|
99
105
|
const dash = isDashed ? ' stroke-dasharray="6 4"' : '';
|
|
100
106
|
if (fromCol === toCol) {
|
|
101
107
|
const cx = actorCx(fromCol);
|
|
102
108
|
const loopH = Math.round(MSG_STEP * 0.55);
|
|
103
109
|
parts.push(`<path d="M${cx.toFixed(1)},${y} L${(cx + SELF_LOOP_W).toFixed(1)},${y} ` +
|
|
104
110
|
`L${(cx + SELF_LOOP_W).toFixed(1)},${y + loopH} L${cx.toFixed(1)},${y + loopH}" ` +
|
|
105
|
-
`fill="none" stroke="${stroke}" stroke-width="1.5"${dash}/>`, arrowhead(cx + SELF_LOOP_W, cx, y + loopH, isDashed));
|
|
111
|
+
`fill="none" stroke="${stroke}" stroke-width="1.5"${dash}/>`, arrowhead(cx + SELF_LOOP_W, cx, y + loopH, isDashed, theme));
|
|
106
112
|
if (edge.label) {
|
|
107
113
|
parts.push(`<text x="${(cx + SELF_LOOP_W + 5).toFixed(1)}" y="${(y + loopH / 2).toFixed(1)}" ` +
|
|
108
|
-
`font-size="${EDGE_LABEL_FONT_SIZE}" fill="${
|
|
114
|
+
`font-size="${EDGE_LABEL_FONT_SIZE}" fill="${theme.textMuted}" dominant-baseline="middle">${esc(edge.label)}</text>`);
|
|
109
115
|
}
|
|
110
116
|
return;
|
|
111
117
|
}
|
|
@@ -114,14 +120,14 @@ export const sequenceTechnique = {
|
|
|
114
120
|
const xMid = (x1 + x2) / 2;
|
|
115
121
|
const dir = x2 > x1 ? 1 : -1;
|
|
116
122
|
parts.push(`<line x1="${x1.toFixed(1)}" y1="${y}" x2="${(x2 - dir * ARROW_SIZE).toFixed(1)}" y2="${y}" ` +
|
|
117
|
-
`stroke="${stroke}" stroke-width="1.5"${dash}/>`, arrowhead(x1, x2, y, isDashed));
|
|
123
|
+
`stroke="${stroke}" stroke-width="1.5"${dash}/>`, arrowhead(x1, x2, y, isDashed, theme));
|
|
118
124
|
if (edge.label) {
|
|
119
125
|
parts.push(`<text x="${xMid.toFixed(1)}" y="${(y - 7).toFixed(1)}" ` +
|
|
120
|
-
`font-size="${EDGE_LABEL_FONT_SIZE}" fill="${
|
|
126
|
+
`font-size="${EDGE_LABEL_FONT_SIZE}" fill="${theme.textBody}" text-anchor="middle">${esc(edge.label)}</text>`);
|
|
121
127
|
}
|
|
122
128
|
});
|
|
123
129
|
return {
|
|
124
|
-
svg: svgDocument(width, height, parts.join('\n')),
|
|
130
|
+
svg: svgDocument(width, height, parts.join('\n'), theme),
|
|
125
131
|
width,
|
|
126
132
|
height,
|
|
127
133
|
boxes: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../../src/adapters/sequence.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAC7E,iBAAiB,EACjB,
|
|
1
|
+
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../../src/adapters/sequence.ts"],"names":[],"mappings":"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"}
|
package/dist/adapters/svg.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Emphasis } from '../domain/spec.js';
|
|
2
|
+
import { type DiagramTheme } from '../domain/theme.js';
|
|
2
3
|
/** Escape text for safe inclusion in SVG/XML text nodes + attributes. */
|
|
3
4
|
export declare function esc(s: string): string;
|
|
4
5
|
/**
|
|
@@ -30,14 +31,14 @@ export declare const PALETTE: Record<Emphasis, {
|
|
|
30
31
|
stroke: string;
|
|
31
32
|
text: string;
|
|
32
33
|
}>;
|
|
33
|
-
/** Resolve a palette entry, defaulting to `normal`. */
|
|
34
|
-
export declare function palette(emphasis: Emphasis | undefined): {
|
|
34
|
+
/** Resolve a palette entry for `theme` (default light), defaulting to `normal`. */
|
|
35
|
+
export declare function palette(emphasis: Emphasis | undefined, theme?: DiagramTheme): {
|
|
35
36
|
fill: string;
|
|
36
37
|
stroke: string;
|
|
37
38
|
text: string;
|
|
38
39
|
};
|
|
39
|
-
/** Build the arrowhead marker defs (filled + open)
|
|
40
|
-
export declare function arrowDefs(): string;
|
|
41
|
-
/** Wrap body markup in a complete, standalone SVG document
|
|
42
|
-
export declare function svgDocument(width: number, height: number, body: string): string;
|
|
40
|
+
/** Build the arrowhead marker defs (filled + open), coloured for `theme`. */
|
|
41
|
+
export declare function arrowDefs(theme?: DiagramTheme): string;
|
|
42
|
+
/** Wrap body markup in a complete, standalone SVG document themed for `theme`. */
|
|
43
|
+
export declare function svgDocument(width: number, height: number, body: string, theme?: DiagramTheme): string;
|
|
43
44
|
//# sourceMappingURL=svg.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../../src/adapters/svg.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../../src/adapters/svg.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEpE,yEAAyE;AACzE,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAuB,GAAG,MAAM,CAEvF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAuB,GAAG,MAAM,EAAE,CAgBlG;AAED;;;GAGG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAOpF,CAAC;AAEF,mFAAmF;AACnF,wBAAgB,OAAO,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAAE,KAAK,GAAE,YAA0B;;;;EAExF;AAED,6EAA6E;AAC7E,wBAAgB,SAAS,CAAC,KAAK,GAAE,YAA0B,GAAG,MAAM,CASnE;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,YAA0B,GAAG,MAAM,CAMlH"}
|
package/dist/adapters/svg.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Satori/resvg techniques in Phase 2 produce SVG via their own engines).
|
|
5
5
|
*/
|
|
6
6
|
import { AVG_CHAR_WIDTH_EM, NODE_LABEL_FONT_SIZE, } from '../constants.js';
|
|
7
|
+
import { LIGHT_THEME } from '../domain/theme.js';
|
|
7
8
|
/** Escape text for safe inclusion in SVG/XML text nodes + attributes. */
|
|
8
9
|
export function esc(s) {
|
|
9
10
|
return s
|
|
@@ -66,26 +67,26 @@ export const PALETTE = {
|
|
|
66
67
|
danger: { fill: '#fee2e2', stroke: '#ef4444', text: '#7f1d1d' },
|
|
67
68
|
success: { fill: '#dcfce7', stroke: '#22c55e', text: '#14532d' },
|
|
68
69
|
};
|
|
69
|
-
/** Resolve a palette entry, defaulting to `normal`. */
|
|
70
|
-
export function palette(emphasis) {
|
|
71
|
-
return
|
|
70
|
+
/** Resolve a palette entry for `theme` (default light), defaulting to `normal`. */
|
|
71
|
+
export function palette(emphasis, theme = LIGHT_THEME) {
|
|
72
|
+
return theme.palette[emphasis ?? 'normal'];
|
|
72
73
|
}
|
|
73
|
-
/** Build the arrowhead marker defs (filled + open)
|
|
74
|
-
export function arrowDefs() {
|
|
74
|
+
/** Build the arrowhead marker defs (filled + open), coloured for `theme`. */
|
|
75
|
+
export function arrowDefs(theme = LIGHT_THEME) {
|
|
75
76
|
return `<defs>
|
|
76
77
|
<marker id="arrow-filled" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
77
|
-
<path d="M0,0 L10,5 L0,10 z" fill="
|
|
78
|
+
<path d="M0,0 L10,5 L0,10 z" fill="${theme.arrow}"/>
|
|
78
79
|
</marker>
|
|
79
80
|
<marker id="arrow-open" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
|
80
|
-
<path d="M0,0 L10,5 L0,10" fill="none" stroke="
|
|
81
|
+
<path d="M0,0 L10,5 L0,10" fill="none" stroke="${theme.arrow}" stroke-width="1.5"/>
|
|
81
82
|
</marker>
|
|
82
83
|
</defs>`;
|
|
83
84
|
}
|
|
84
|
-
/** Wrap body markup in a complete, standalone SVG document
|
|
85
|
-
export function svgDocument(width, height, body) {
|
|
85
|
+
/** Wrap body markup in a complete, standalone SVG document themed for `theme`. */
|
|
86
|
+
export function svgDocument(width, height, body, theme = LIGHT_THEME) {
|
|
86
87
|
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" font-family="ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif">
|
|
87
|
-
<rect x="0" y="0" width="${width}" height="${height}" fill="
|
|
88
|
-
${arrowDefs()}
|
|
88
|
+
<rect x="0" y="0" width="${width}" height="${height}" fill="${theme.bg}"/>
|
|
89
|
+
${arrowDefs(theme)}
|
|
89
90
|
${body}
|
|
90
91
|
</svg>`;
|
|
91
92
|
}
|