@sgummalla-works/sketchon 0.1.0 → 0.2.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/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 +6 -4
- package/dist/adapters/satori.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/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/README.md
CHANGED
|
@@ -50,6 +50,40 @@ const { svg, width, height } = await renderDiagram(spec);
|
|
|
50
50
|
// svg is a standalone <svg> string, ready for display or rasterisation
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
## Node vs browser
|
|
54
|
+
|
|
55
|
+
The package runs in **both** environments and bundlers pick the right build
|
|
56
|
+
automatically (via the `browser` / `node` export conditions). The only
|
|
57
|
+
difference is where the Satori engine gets its fonts + emoji:
|
|
58
|
+
|
|
59
|
+
| Environment | Default asset source |
|
|
60
|
+
|---|---|
|
|
61
|
+
| **Node** (`index.js`) | Bundled Inter TTFs + Twemoji read from disk (`assets/`) |
|
|
62
|
+
| **Browser** (`index.browser.js`) | Inter weights + Twemoji SVGs fetched from a CDN, cached in memory |
|
|
63
|
+
|
|
64
|
+
Everything else — the spec, validation, routing, all four engines — is
|
|
65
|
+
identical. The public API is the same on both.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// In a browser app (e.g. React), the import resolves to the browser build:
|
|
69
|
+
import { renderDiagram } from '@sgummalla-works/sketchon';
|
|
70
|
+
const { svg } = await renderDiagram(spec); // fonts/emoji fetched on first render
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Overriding fonts / emoji (`configureAssets`)
|
|
74
|
+
|
|
75
|
+
The defaults work out of the box. To go fully offline (no CDN fetch) or use a
|
|
76
|
+
custom font, inject your own provider — only the methods you pass are replaced:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { configureAssets } from '@sgummalla-works/sketchon';
|
|
80
|
+
|
|
81
|
+
configureAssets({
|
|
82
|
+
// e.g. bundle the font with your app and hand Satori the bytes directly:
|
|
83
|
+
loadFonts: () => [{ name: 'Inter', data: myInterArrayBuffer, weight: 400, style: 'normal' }],
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
53
87
|
## Diagram kinds and engines
|
|
54
88
|
|
|
55
89
|
| `kind` | Engine | Use for |
|
|
@@ -173,9 +207,11 @@ const spec: DiagramSpec = {
|
|
|
173
207
|
| `TECHNIQUES` | Array of all registered engines (used by the lab harness). |
|
|
174
208
|
| `getTechnique(key)` | Look up a specific engine by key. |
|
|
175
209
|
| `DiagramSpec` + all spec types | Re-exported from `domain/spec.ts`. |
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
210
|
+
| `configureAssets(overrides)` | Override the font/emoji source (`{ loadFonts?, emojiToDataUri? }`). Only the methods passed are replaced. |
|
|
211
|
+
| `setAssetProvider(provider)` | Replace the whole asset provider (advanced; the entries call this to bind the env default). |
|
|
212
|
+
| `AssetProvider`, `SketchonFont` | Types for the injection point. |
|
|
213
|
+
| `loadFonts` | **Node build only**: loads bundled Inter TTFs from disk for Satori. |
|
|
214
|
+
| `emojiToDataUri` | **Node build only**: resolves an emoji to a Twemoji SVG data-URI from disk. |
|
|
179
215
|
|
|
180
216
|
## How to add a new layout engine
|
|
181
217
|
|
|
@@ -194,4 +230,4 @@ npm run test:watch # watch mode
|
|
|
194
230
|
npm run test:coverage # with coverage report
|
|
195
231
|
```
|
|
196
232
|
|
|
197
|
-
Tests: **
|
|
233
|
+
Tests: **85 unit tests** across domain validation, application routing/registry, the adapters (incl. the asset provider + browser provider), and the architecture guard.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.browser.d.ts","sourceRoot":"","sources":["../../src/adapters/assets.browser.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,2BAA2B,CAAC;AAsD7E,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,EAAE,aAA6C,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser asset provider — the default binding for the browser entry
|
|
3
|
+
* (`index.browser.ts`). A browser has no filesystem, so it fetches the same
|
|
4
|
+
* Inter weights + Twemoji SVGs the Node provider reads from disk, caching each
|
|
5
|
+
* in memory so a given font/emoji is fetched at most once per session.
|
|
6
|
+
*
|
|
7
|
+
* No `node:` imports are reachable from here, so the browser entry's whole graph
|
|
8
|
+
* is bundler-safe. Consumers who want zero network at render time inject bundled
|
|
9
|
+
* fonts via `configureAssets({ loadFonts })`.
|
|
10
|
+
*/
|
|
11
|
+
import { INTER_FONT_CDN_BASE, INTER_FONT_WEIGHTS, TWEMOJI_SVG_CDN_BASE } from '../constants.js';
|
|
12
|
+
import { emojiCode } from './emoji-code.js';
|
|
13
|
+
let fontCache = null;
|
|
14
|
+
const emojiCache = new Map(); // code -> data URI
|
|
15
|
+
/** UTF-8-safe base64 data-URI for an SVG string (the browser has no Buffer). */
|
|
16
|
+
function svgToDataUri(svg) {
|
|
17
|
+
const bytes = new TextEncoder().encode(svg);
|
|
18
|
+
let binary = '';
|
|
19
|
+
for (const b of bytes)
|
|
20
|
+
binary += String.fromCharCode(b);
|
|
21
|
+
return `data:image/svg+xml;base64,${btoa(binary)}`;
|
|
22
|
+
}
|
|
23
|
+
/** A 1×1 transparent SVG, returned when an emoji can't be resolved (offline / 404). */
|
|
24
|
+
const TRANSPARENT = svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>');
|
|
25
|
+
/**
|
|
26
|
+
* Fetch the Inter weights Satori renders text with, cached after the first call.
|
|
27
|
+
*
|
|
28
|
+
* @returns the font faces as ArrayBuffers.
|
|
29
|
+
*/
|
|
30
|
+
async function loadFonts() {
|
|
31
|
+
if (fontCache)
|
|
32
|
+
return fontCache;
|
|
33
|
+
fontCache = await Promise.all(INTER_FONT_WEIGHTS.map(async (weight) => {
|
|
34
|
+
const res = await fetch(`${INTER_FONT_CDN_BASE}/inter-latin-${weight}-normal.woff`);
|
|
35
|
+
return { name: 'Inter', weight, style: 'normal', data: await res.arrayBuffer() };
|
|
36
|
+
}));
|
|
37
|
+
return fontCache;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve an emoji to a Twemoji SVG data-URI via fetch + in-memory cache.
|
|
41
|
+
*
|
|
42
|
+
* @param emoji a single emoji grapheme.
|
|
43
|
+
* @returns a data-URI for the Twemoji SVG, or a transparent pixel if unresolved.
|
|
44
|
+
*/
|
|
45
|
+
async function emojiToDataUri(emoji) {
|
|
46
|
+
const code = emojiCode(emoji);
|
|
47
|
+
const cached = emojiCache.get(code);
|
|
48
|
+
if (cached)
|
|
49
|
+
return cached;
|
|
50
|
+
let uri = TRANSPARENT;
|
|
51
|
+
try {
|
|
52
|
+
const res = await fetch(`${TWEMOJI_SVG_CDN_BASE}/${code}.svg`);
|
|
53
|
+
if (res.ok)
|
|
54
|
+
uri = svgToDataUri(await res.text());
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// offline or fetch error — fall through to the transparent placeholder
|
|
58
|
+
}
|
|
59
|
+
emojiCache.set(code, uri);
|
|
60
|
+
return uri;
|
|
61
|
+
}
|
|
62
|
+
/** Fetch-backed provider: CDN fonts + CDN emoji, both cached in memory. */
|
|
63
|
+
export const browserAssetProvider = { loadFonts, emojiToDataUri };
|
|
64
|
+
//# sourceMappingURL=assets.browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.browser.js","sourceRoot":"","sources":["../../src/adapters/assets.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAChG,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,IAAI,SAAS,GAA0B,IAAI,CAAC;AAC5C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,mBAAmB;AAEjE,gFAAgF;AAChF,SAAS,YAAY,CAAC,GAAW;IAC/B,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,6BAA6B,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AACrD,CAAC;AAED,uFAAuF;AACvF,MAAM,WAAW,GAAG,YAAY,CAAC,gEAAgE,CAAC,CAAC;AAEnG;;;;GAIG;AACH,KAAK,UAAU,SAAS;IACtB,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CAC3B,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAyB,EAAE;QAC7D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,mBAAmB,gBAAgB,MAAM,cAAc,CAAC,CAAC;QACpF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;IACnF,CAAC,CAAC,CACH,CAAC;IACF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,cAAc,CAAC,KAAa;IACzC,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,IAAI,GAAG,GAAG,WAAW,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,oBAAoB,IAAI,IAAI,MAAM,CAAC,CAAC;QAC/D,IAAI,GAAG,CAAC,EAAE;YAAE,GAAG,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;IACzE,CAAC;IACD,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC1B,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,oBAAoB,GAAkB,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset provider registry — the single, swappable binding the Satori engine
|
|
3
|
+
* reads its fonts + emoji from.
|
|
4
|
+
*
|
|
5
|
+
* Holds a process-wide provider bound by the composition root: the Node entry
|
|
6
|
+
* binds the disk provider, the browser entry binds the fetch provider. Kept as
|
|
7
|
+
* a module singleton because rendering is a stateless, app-wide concern and the
|
|
8
|
+
* font/emoji caches are already module-scoped. Consumers override it (whole or
|
|
9
|
+
* in part) via `configureAssets` — dependency injection at the edge.
|
|
10
|
+
*/
|
|
11
|
+
import type { AssetProvider } from '../ports/AssetProvider.js';
|
|
12
|
+
/**
|
|
13
|
+
* Bind the base provider. Called once by each composition root.
|
|
14
|
+
*
|
|
15
|
+
* @param provider the environment-specific provider (disk or fetch).
|
|
16
|
+
*/
|
|
17
|
+
export declare function setAssetProvider(provider: AssetProvider): void;
|
|
18
|
+
/**
|
|
19
|
+
* Override part (or all) of the active provider — the public injection point.
|
|
20
|
+
* Merges over whatever the composition root bound, so a caller can replace just
|
|
21
|
+
* `loadFonts` (e.g. bundled offline fonts) and keep the default emoji resolver.
|
|
22
|
+
*
|
|
23
|
+
* @param overrides the provider methods to replace.
|
|
24
|
+
* @throws Error if no base provider has been bound yet (import an entry first).
|
|
25
|
+
*/
|
|
26
|
+
export declare function configureAssets(overrides: Partial<AssetProvider>): void;
|
|
27
|
+
/**
|
|
28
|
+
* The active provider, used by the Satori engine at render time.
|
|
29
|
+
*
|
|
30
|
+
* @returns the bound AssetProvider.
|
|
31
|
+
* @throws Error if no provider has been bound (no package entry imported).
|
|
32
|
+
*/
|
|
33
|
+
export declare function getAssetProvider(): AssetProvider;
|
|
34
|
+
//# sourceMappingURL=assets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/adapters/assets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAQ/D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAGvE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
let current = null;
|
|
2
|
+
const UNBOUND = 'sketchon: no AssetProvider bound. Import "@sgummalla-works/sketchon" (its Node ' +
|
|
3
|
+
'or browser entry binds one automatically), or call setAssetProvider() first.';
|
|
4
|
+
/**
|
|
5
|
+
* Bind the base provider. Called once by each composition root.
|
|
6
|
+
*
|
|
7
|
+
* @param provider the environment-specific provider (disk or fetch).
|
|
8
|
+
*/
|
|
9
|
+
export function setAssetProvider(provider) {
|
|
10
|
+
current = provider;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Override part (or all) of the active provider — the public injection point.
|
|
14
|
+
* Merges over whatever the composition root bound, so a caller can replace just
|
|
15
|
+
* `loadFonts` (e.g. bundled offline fonts) and keep the default emoji resolver.
|
|
16
|
+
*
|
|
17
|
+
* @param overrides the provider methods to replace.
|
|
18
|
+
* @throws Error if no base provider has been bound yet (import an entry first).
|
|
19
|
+
*/
|
|
20
|
+
export function configureAssets(overrides) {
|
|
21
|
+
if (!current)
|
|
22
|
+
throw new Error(UNBOUND);
|
|
23
|
+
current = { ...current, ...overrides };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The active provider, used by the Satori engine at render time.
|
|
27
|
+
*
|
|
28
|
+
* @returns the bound AssetProvider.
|
|
29
|
+
* @throws Error if no provider has been bound (no package entry imported).
|
|
30
|
+
*/
|
|
31
|
+
export function getAssetProvider() {
|
|
32
|
+
if (!current)
|
|
33
|
+
throw new Error(UNBOUND);
|
|
34
|
+
return current;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/adapters/assets.ts"],"names":[],"mappings":"AAYA,IAAI,OAAO,GAAyB,IAAI,CAAC;AAEzC,MAAM,OAAO,GACX,iFAAiF;IACjF,8EAA8E,CAAC;AAEjF;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAuB;IACtD,OAAO,GAAG,QAAQ,CAAC;AACrB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiC;IAC/D,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.node.d.ts","sourceRoot":"","sources":["../../src/adapters/assets.node.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB,EAAE,aAG/B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node asset provider — the default binding for the Node entry (`index.ts`).
|
|
3
|
+
* Reads the bundled Inter fonts + Twemoji SVGs off disk. See `assets.browser.ts`
|
|
4
|
+
* for the browser (fetch) counterpart.
|
|
5
|
+
*
|
|
6
|
+
* This is the ONLY asset module that pulls in the filesystem loaders, so it must
|
|
7
|
+
* never be imported by the browser entry — keeping `fs` out of the browser graph.
|
|
8
|
+
*/
|
|
9
|
+
import { loadFonts } from './fonts.js';
|
|
10
|
+
import { emojiToDataUri } from './emoji.js';
|
|
11
|
+
/** Disk-backed provider: bundled fonts, disk-cached emoji. */
|
|
12
|
+
export const nodeAssetProvider = {
|
|
13
|
+
loadFonts,
|
|
14
|
+
emojiToDataUri,
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=assets.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.node.js","sourceRoot":"","sources":["../../src/adapters/assets.node.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C,8DAA8D;AAC9D,MAAM,CAAC,MAAM,iBAAiB,GAAkB;IAC9C,SAAS;IACT,cAAc;CACf,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Twemoji asset code for an emoji grapheme (FE0F stripped unless ZWJ-joined).
|
|
3
|
+
*
|
|
4
|
+
* @param emoji a single emoji grapheme.
|
|
5
|
+
* @returns the dash-joined hex codepoint string used as the Twemoji filename.
|
|
6
|
+
*/
|
|
7
|
+
export declare function emojiCode(emoji: string): string;
|
|
8
|
+
//# sourceMappingURL=emoji-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji-code.d.ts","sourceRoot":"","sources":["../../src/adapters/emoji-code.ts"],"names":[],"mappings":"AA8BA;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG/C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emoji codepoint derivation — pure and environment-agnostic (no filesystem,
|
|
3
|
+
* no Buffer). Both the Node and browser asset providers use it to turn an emoji
|
|
4
|
+
* grapheme into the Twemoji asset code.
|
|
5
|
+
*
|
|
6
|
+
* Codepoint derivation follows Twemoji's own filename rule: strip the FE0F
|
|
7
|
+
* variation selector UNLESS the sequence is a ZWJ join — otherwise the asset
|
|
8
|
+
* name won't match (e.g. ⚙️ U+2699 U+FE0F → "2699.svg").
|
|
9
|
+
*/
|
|
10
|
+
const U200D = String.fromCharCode(0x200d); // zero-width joiner
|
|
11
|
+
const UFE0F = /️/g; // variation selector-16
|
|
12
|
+
/** Convert a (possibly surrogate-pair) string to dash-joined hex codepoints. */
|
|
13
|
+
function toCodePoint(s) {
|
|
14
|
+
const out = [];
|
|
15
|
+
let prev = 0;
|
|
16
|
+
for (let i = 0; i < s.length; i++) {
|
|
17
|
+
const c = s.charCodeAt(i);
|
|
18
|
+
if (prev) {
|
|
19
|
+
out.push((0x10000 + ((prev - 0xd800) << 10) + (c - 0xdc00)).toString(16));
|
|
20
|
+
prev = 0;
|
|
21
|
+
}
|
|
22
|
+
else if (c >= 0xd800 && c <= 0xdbff) {
|
|
23
|
+
prev = c;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
out.push(c.toString(16));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return out.join('-');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Twemoji asset code for an emoji grapheme (FE0F stripped unless ZWJ-joined).
|
|
33
|
+
*
|
|
34
|
+
* @param emoji a single emoji grapheme.
|
|
35
|
+
* @returns the dash-joined hex codepoint string used as the Twemoji filename.
|
|
36
|
+
*/
|
|
37
|
+
export function emojiCode(emoji) {
|
|
38
|
+
const grapheme = emoji.indexOf(U200D) < 0 ? emoji.replace(UFE0F, '') : emoji;
|
|
39
|
+
return toCodePoint(grapheme);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=emoji-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emoji-code.js","sourceRoot":"","sources":["../../src/adapters/emoji-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,oBAAoB;AAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,wBAAwB;AAE5C,gFAAgF;AAChF,SAAS,WAAW,CAAC,CAAS;IAC5B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,IAAI,EAAE,CAAC;YACT,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1E,IAAI,GAAG,CAAC,CAAC;QACX,CAAC;aAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;YACtC,IAAI,GAAG,CAAC,CAAC;QACX,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7E,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC"}
|
package/dist/adapters/emoji.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
/** Twemoji asset code for an emoji grapheme (FE0F stripped unless ZWJ-joined). */
|
|
2
|
-
export declare function emojiCode(emoji: string): string;
|
|
3
1
|
/**
|
|
4
2
|
* Resolve an emoji to a base64 SVG data-URI for Satori, via disk + memory cache.
|
|
5
3
|
*
|
|
6
|
-
* @param emoji a single emoji grapheme
|
|
7
|
-
* @returns a data-URI for the Twemoji SVG, or a transparent pixel if unresolved
|
|
4
|
+
* @param emoji a single emoji grapheme.
|
|
5
|
+
* @returns a data-URI for the Twemoji SVG, or a transparent pixel if unresolved.
|
|
8
6
|
*/
|
|
9
7
|
export declare function emojiToDataUri(emoji: string): Promise<string>;
|
|
10
8
|
//# sourceMappingURL=emoji.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emoji.d.ts","sourceRoot":"","sources":["../../src/adapters/emoji.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"emoji.d.ts","sourceRoot":"","sources":["../../src/adapters/emoji.ts"],"names":[],"mappings":"AA0BA;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BnE"}
|
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;AAmRrE,eAAO,MAAM,eAAe,EAAE,SAqC7B,CAAC"}
|
package/dist/adapters/satori.js
CHANGED
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
* overlap) — fidelity + the visual gallery are the real signal here.
|
|
17
17
|
*/
|
|
18
18
|
import satori from 'satori';
|
|
19
|
-
import {
|
|
20
|
-
import { emojiToDataUri } from './emoji.js';
|
|
19
|
+
import { getAssetProvider } from './assets.js';
|
|
21
20
|
import { CARD_PALETTE, CHECKPOINT_COLORS, el, monogram, stripEmoji, } from './satori-helpers.js';
|
|
22
21
|
/**
|
|
23
22
|
* Render a node's leading glyph. If the node carries an emoji `icon`, emit it as
|
|
@@ -236,7 +235,10 @@ 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();
|
|
240
242
|
const height = estimateHeight(spec);
|
|
241
243
|
const tree = buildTree(spec);
|
|
242
244
|
const svg = await satori(tree, {
|
|
@@ -246,7 +248,7 @@ export const satoriTechnique = {
|
|
|
246
248
|
// Satori has no emoji font; resolve each emoji grapheme to a Twemoji SVG.
|
|
247
249
|
loadAdditionalAsset: async (code, segment) => {
|
|
248
250
|
if (code === 'emoji')
|
|
249
|
-
return emojiToDataUri(segment);
|
|
251
|
+
return assets.emojiToDataUri(segment);
|
|
250
252
|
return '';
|
|
251
253
|
},
|
|
252
254
|
});
|
|
@@ -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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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared COMPOSITION ROOT — wires the engine registry + router and re-exports
|
|
3
|
+
* the environment-agnostic public API.
|
|
4
|
+
*
|
|
5
|
+
* ── HEXAGONAL ARCHITECTURE — COMPOSITION ROOT RULES ──────────────────────────
|
|
6
|
+
* This module (together with the thin entry points that import it) is the ONLY
|
|
7
|
+
* place that may import concrete adapters. All other application/domain files
|
|
8
|
+
* stay free of adapter imports — enforced by the architecture guard tests
|
|
9
|
+
* (src/application/architecture.test.ts).
|
|
10
|
+
*
|
|
11
|
+
* Dependency flow (all arrows point inward):
|
|
12
|
+
* adapters/ ──► application/ ──► domain/
|
|
13
|
+
* adapters/ ──► ports/
|
|
14
|
+
*
|
|
15
|
+
* It deliberately does NOT bind an AssetProvider. Each entry point binds the
|
|
16
|
+
* one for its environment:
|
|
17
|
+
* - index.ts → Node: disk-backed provider
|
|
18
|
+
* - index.browser.ts → browser: fetch-backed provider
|
|
19
|
+
* Keeping the binding out of here is what lets the browser entry stay free of
|
|
20
|
+
* any `node:` import.
|
|
21
|
+
*/
|
|
22
|
+
export * from './domain/spec.js';
|
|
23
|
+
export * from './domain/validate.js';
|
|
24
|
+
export * from './domain/theme.js';
|
|
25
|
+
export type { Technique, RenderResult, PlacedBox, PlacedEdge, StructuralFeatures, } from './ports/Technique.js';
|
|
26
|
+
export type { AssetProvider, SketchonFont } from './ports/AssetProvider.js';
|
|
27
|
+
export { TechniqueRegistry } from './application/registry.js';
|
|
28
|
+
export { type EngineKey } from './application/router.js';
|
|
29
|
+
export * from './constants.js';
|
|
30
|
+
export { esc, estimateTextWidth, wrapText, palette, PALETTE, arrowDefs, svgDocument, } from './adapters/svg.js';
|
|
31
|
+
export { emojiCode } from './adapters/emoji-code.js';
|
|
32
|
+
export { configureAssets, setAssetProvider } from './adapters/assets.js';
|
|
33
|
+
export { satoriTechnique } from './adapters/satori.js';
|
|
34
|
+
export { elkTechnique } from './adapters/elk.js';
|
|
35
|
+
export { sequenceTechnique } from './adapters/sequence.js';
|
|
36
|
+
export { baselineTechnique } from './adapters/baseline.js';
|
|
37
|
+
import { TechniqueRegistry } from './application/registry.js';
|
|
38
|
+
/**
|
|
39
|
+
* The application-wide registry, pre-populated with all built-in engines.
|
|
40
|
+
* Consumers may call `.register()` to add custom engines.
|
|
41
|
+
*/
|
|
42
|
+
export declare const REGISTRY: TechniqueRegistry;
|
|
43
|
+
/** All registered techniques — used by the lab harness. */
|
|
44
|
+
export declare const TECHNIQUES: import("./ports/Technique.js").Technique[];
|
|
45
|
+
/** Select the engine key that would render a spec (logging / debugging). */
|
|
46
|
+
export declare const selectEngineKey: (spec: import("./domain/spec.js").DiagramSpec) => import("./application/router.js").EngineKey;
|
|
47
|
+
/** Resolve the Technique that will render a spec. */
|
|
48
|
+
export declare const selectEngine: (spec: import("./domain/spec.js").DiagramSpec) => import("./ports/Technique.js").Technique;
|
|
49
|
+
/**
|
|
50
|
+
* Production render entry point. Validates routing and delegates to the chosen
|
|
51
|
+
* layout engine. Fonts + emoji come from the entry-bound AssetProvider.
|
|
52
|
+
*/
|
|
53
|
+
export declare const renderDiagram: (spec: import("./domain/spec.js").DiagramSpec) => import("./ports/Technique.js").RenderResult | Promise<import("./ports/Technique.js").RenderResult>;
|
|
54
|
+
//# sourceMappingURL=composition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composition.d.ts","sourceRoot":"","sources":["../src/composition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAGlC,YAAY,EACV,SAAS,EACT,YAAY,EACZ,SAAS,EACT,UAAU,EACV,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGzD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,GAAG,EACH,iBAAiB,EACjB,QAAQ,EACR,OAAO,EACP,OAAO,EACP,SAAS,EACT,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGzE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAO9D;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,iBAImB,CAAC;AAI3C,2DAA2D;AAC3D,eAAO,MAAM,UAAU,4CAAwB,CAAC;AAEhD,4EAA4E;AAC5E,eAAO,MAAM,eAAe,+FAAsC,CAAC;AAEnE,qDAAqD;AACrD,eAAO,MAAM,YAAY,4FAAmC,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,aAAa,sJAAoC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared COMPOSITION ROOT — wires the engine registry + router and re-exports
|
|
3
|
+
* the environment-agnostic public API.
|
|
4
|
+
*
|
|
5
|
+
* ── HEXAGONAL ARCHITECTURE — COMPOSITION ROOT RULES ──────────────────────────
|
|
6
|
+
* This module (together with the thin entry points that import it) is the ONLY
|
|
7
|
+
* place that may import concrete adapters. All other application/domain files
|
|
8
|
+
* stay free of adapter imports — enforced by the architecture guard tests
|
|
9
|
+
* (src/application/architecture.test.ts).
|
|
10
|
+
*
|
|
11
|
+
* Dependency flow (all arrows point inward):
|
|
12
|
+
* adapters/ ──► application/ ──► domain/
|
|
13
|
+
* adapters/ ──► ports/
|
|
14
|
+
*
|
|
15
|
+
* It deliberately does NOT bind an AssetProvider. Each entry point binds the
|
|
16
|
+
* one for its environment:
|
|
17
|
+
* - index.ts → Node: disk-backed provider
|
|
18
|
+
* - index.browser.ts → browser: fetch-backed provider
|
|
19
|
+
* Keeping the binding out of here is what lets the browser entry stay free of
|
|
20
|
+
* any `node:` import.
|
|
21
|
+
*/
|
|
22
|
+
// ── Domain (pure — zero external deps) ───────────────────────────────────────
|
|
23
|
+
export * from './domain/spec.js';
|
|
24
|
+
export * from './domain/validate.js';
|
|
25
|
+
export * from './domain/theme.js';
|
|
26
|
+
// ── Application (registry + router — no adapter imports) ──────────────────────
|
|
27
|
+
export { TechniqueRegistry } from './application/registry.js';
|
|
28
|
+
export {} from './application/router.js';
|
|
29
|
+
// ── Constants + shared render helpers ────────────────────────────────────────
|
|
30
|
+
export * from './constants.js';
|
|
31
|
+
export { esc, estimateTextWidth, wrapText, palette, PALETTE, arrowDefs, svgDocument, } from './adapters/svg.js';
|
|
32
|
+
// ── Browser-safe helpers + the public asset-injection point ───────────────────
|
|
33
|
+
export { emojiCode } from './adapters/emoji-code.js';
|
|
34
|
+
export { configureAssets, setAssetProvider } from './adapters/assets.js';
|
|
35
|
+
// ── Concrete adapters (exported for advanced use + the lab) ───────────────────
|
|
36
|
+
export { satoriTechnique } from './adapters/satori.js';
|
|
37
|
+
export { elkTechnique } from './adapters/elk.js';
|
|
38
|
+
export { sequenceTechnique } from './adapters/sequence.js';
|
|
39
|
+
export { baselineTechnique } from './adapters/baseline.js';
|
|
40
|
+
// ── Registry + router wiring ──────────────────────────────────────────────────
|
|
41
|
+
import { TechniqueRegistry } from './application/registry.js';
|
|
42
|
+
import { Router } from './application/router.js';
|
|
43
|
+
import { satoriTechnique } from './adapters/satori.js';
|
|
44
|
+
import { elkTechnique } from './adapters/elk.js';
|
|
45
|
+
import { sequenceTechnique } from './adapters/sequence.js';
|
|
46
|
+
import { baselineTechnique } from './adapters/baseline.js';
|
|
47
|
+
/**
|
|
48
|
+
* The application-wide registry, pre-populated with all built-in engines.
|
|
49
|
+
* Consumers may call `.register()` to add custom engines.
|
|
50
|
+
*/
|
|
51
|
+
export const REGISTRY = new TechniqueRegistry()
|
|
52
|
+
.register('baseline', baselineTechnique)
|
|
53
|
+
.register('satori', satoriTechnique)
|
|
54
|
+
.register('elk', elkTechnique)
|
|
55
|
+
.register('sequence', sequenceTechnique);
|
|
56
|
+
const router = new Router(REGISTRY);
|
|
57
|
+
/** All registered techniques — used by the lab harness. */
|
|
58
|
+
export const TECHNIQUES = REGISTRY.techniques();
|
|
59
|
+
/** Select the engine key that would render a spec (logging / debugging). */
|
|
60
|
+
export const selectEngineKey = router.selectEngineKey.bind(router);
|
|
61
|
+
/** Resolve the Technique that will render a spec. */
|
|
62
|
+
export const selectEngine = router.selectEngine.bind(router);
|
|
63
|
+
/**
|
|
64
|
+
* Production render entry point. Validates routing and delegates to the chosen
|
|
65
|
+
* layout engine. Fonts + emoji come from the entry-bound AssetProvider.
|
|
66
|
+
*/
|
|
67
|
+
export const renderDiagram = router.renderDiagram.bind(router);
|
|
68
|
+
//# sourceMappingURL=composition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composition.js","sourceRoot":"","sources":["../src/composition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,gFAAgF;AAChF,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAYlC,iFAAiF;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAkB,MAAM,yBAAyB,CAAC;AAEzD,gFAAgF;AAChF,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,GAAG,EACH,iBAAiB,EACjB,QAAQ,EACR,OAAO,EACP,OAAO,EACP,SAAS,EACT,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,iFAAiF;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEzE,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,iFAAiF;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAsB,IAAI,iBAAiB,EAAE;KAC/D,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;KACvC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;KACnC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;KAC7B,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAE3C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEpC,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;AAEhD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAEnE,qDAAqD;AACrD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAE7D;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -16,6 +16,9 @@ export declare const NODE_MAX_WIDTH = 240;
|
|
|
16
16
|
export declare const LAYER_GAP = 90;
|
|
17
17
|
export declare const NODE_GAP = 36;
|
|
18
18
|
export declare const CANVAS_PADDING = 40;
|
|
19
|
+
export declare const INTER_FONT_CDN_BASE = "https://cdn.jsdelivr.net/npm/@fontsource/inter@5.1.1/files";
|
|
20
|
+
export declare const INTER_FONT_WEIGHTS: readonly [400, 600, 700];
|
|
21
|
+
export declare const TWEMOJI_SVG_CDN_BASE = "https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg";
|
|
19
22
|
export declare const SCORE_START = 100;
|
|
20
23
|
export declare const PENALTY_PER_OVERLAP_PAIR = 12;
|
|
21
24
|
export declare const PENALTY_PER_OFFCANVAS_BOX = 10;
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAGvC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,cAAc,MAAM,CAAC;AAGlC,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,QAAQ,KAAK,CAAC;AAC3B,eAAO,MAAM,cAAc,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAGvC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,cAAc,MAAM,CAAC;AAGlC,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,QAAQ,KAAK,CAAC;AAC3B,eAAO,MAAM,cAAc,KAAK,CAAC;AASjC,eAAO,MAAM,mBAAmB,+DAA+D,CAAC;AAChG,eAAO,MAAM,kBAAkB,0BAA2B,CAAC;AAG3D,eAAO,MAAM,oBAAoB,kEAAkE,CAAC;AAKpG,eAAO,MAAM,WAAW,MAAM,CAAC;AAC/B,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAC5C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAC3C,eAAO,MAAM,0BAA0B,IAAI,CAAC"}
|
package/dist/constants.js
CHANGED
|
@@ -23,6 +23,18 @@ export const NODE_MAX_WIDTH = 240;
|
|
|
23
23
|
export const LAYER_GAP = 90; // gap between layers (rank direction)
|
|
24
24
|
export const NODE_GAP = 36; // gap between siblings within a layer
|
|
25
25
|
export const CANVAS_PADDING = 40; // margin around the whole drawing
|
|
26
|
+
// ── Browser asset sources (CDN) ─────────────────────────────────────────────
|
|
27
|
+
// The browser AssetProvider has no disk, so it fetches the same assets the Node
|
|
28
|
+
// provider reads from `assets/`. Pinned to specific versions so a CDN change
|
|
29
|
+
// cannot silently alter rendering. Consumers go fully offline by injecting
|
|
30
|
+
// bundled fonts via `configureAssets()`.
|
|
31
|
+
// - @fontsource ships Satori-compatible `.woff` (NOT `.woff2`, which Satori
|
|
32
|
+
// cannot decode); file names follow `inter-latin-<weight>-normal.woff`.
|
|
33
|
+
export const INTER_FONT_CDN_BASE = 'https://cdn.jsdelivr.net/npm/@fontsource/inter@5.1.1/files';
|
|
34
|
+
export const INTER_FONT_WEIGHTS = [400, 600, 700];
|
|
35
|
+
// jdecked's maintained Twemoji fork — shared by the Node disk provider and the
|
|
36
|
+
// browser fetch provider so the asset code is derived identically.
|
|
37
|
+
export const TWEMOJI_SVG_CDN_BASE = 'https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/svg';
|
|
26
38
|
// ── Eval thresholds + scoring weights ───────────────────────────────────────
|
|
27
39
|
// Composite score starts at 100; each problem subtracts its weight (clamped
|
|
28
40
|
// at 0). Weights encode "how bad is this for a reader."
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,+EAA+E;AAC/E,4EAA4E;AAC5E,gFAAgF;AAChF,2EAA2E;AAC3E,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAC1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC,sCAAsC;AACnE,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,sCAAsC;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC,CAAC,kCAAkC;AAEpE,+EAA+E;AAC/E,4EAA4E;AAC5E,wDAAwD;AACxD,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAC/B,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC,CAAC,+BAA+B;AAC3E,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC,CAAC,0BAA0B;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,CAAC,2BAA2B;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,CAAC,qBAAqB;AACjE,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,CAAC,4BAA4B"}
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,+EAA+E;AAC/E,4EAA4E;AAC5E,gFAAgF;AAChF,2EAA2E;AAC3E,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAC1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAElC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC,sCAAsC;AACnE,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,sCAAsC;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC,CAAC,kCAAkC;AAEpE,+EAA+E;AAC/E,gFAAgF;AAChF,6EAA6E;AAC7E,2EAA2E;AAC3E,yCAAyC;AACzC,8EAA8E;AAC9E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,mBAAmB,GAAG,4DAA4D,CAAC;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAC3D,+EAA+E;AAC/E,mEAAmE;AACnE,MAAM,CAAC,MAAM,oBAAoB,GAAG,+DAA+D,CAAC;AAEpG,+EAA+E;AAC/E,4EAA4E;AAC5E,wDAAwD;AACxD,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAC/B,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC,CAAC,+BAA+B;AAC3E,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC,CAAC,0BAA0B;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,CAAC,2BAA2B;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,CAAC,qBAAqB;AACjE,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,CAAC,4BAA4B"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sgummalla-works/sketchon — BROWSER entry point.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the shared public API (see composition.ts) and binds the
|
|
5
|
+
* fetch-backed AssetProvider (Inter weights + Twemoji SVGs from a CDN, cached in
|
|
6
|
+
* memory). NO `node:` import is reachable from here, so this entry is safe to
|
|
7
|
+
* bundle for the browser. Bundlers pick it automatically via the package's
|
|
8
|
+
* "browser" export condition.
|
|
9
|
+
*
|
|
10
|
+
* To avoid the network at render time, inject bundled fonts:
|
|
11
|
+
* import { configureAssets } from '@sgummalla-works/sketchon';
|
|
12
|
+
* configureAssets({ loadFonts: () => myBundledInterFaces });
|
|
13
|
+
*/
|
|
14
|
+
export * from './composition.js';
|
|
15
|
+
//# sourceMappingURL=index.browser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sgummalla-works/sketchon — BROWSER entry point.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the shared public API (see composition.ts) and binds the
|
|
5
|
+
* fetch-backed AssetProvider (Inter weights + Twemoji SVGs from a CDN, cached in
|
|
6
|
+
* memory). NO `node:` import is reachable from here, so this entry is safe to
|
|
7
|
+
* bundle for the browser. Bundlers pick it automatically via the package's
|
|
8
|
+
* "browser" export condition.
|
|
9
|
+
*
|
|
10
|
+
* To avoid the network at render time, inject bundled fonts:
|
|
11
|
+
* import { configureAssets } from '@sgummalla-works/sketchon';
|
|
12
|
+
* configureAssets({ loadFonts: () => myBundledInterFaces });
|
|
13
|
+
*/
|
|
14
|
+
export * from './composition.js';
|
|
15
|
+
// ── Bind the fetch-backed provider as the default for this environment ────────
|
|
16
|
+
import { setAssetProvider } from './adapters/assets.js';
|
|
17
|
+
import { browserAssetProvider } from './adapters/assets.browser.js';
|
|
18
|
+
setAssetProvider(browserAssetProvider);
|
|
19
|
+
//# sourceMappingURL=index.browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,kBAAkB,CAAC;AAEjC,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,gBAAgB,CAAC,oBAAoB,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,62 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @sgummalla-works/sketchon —
|
|
2
|
+
* @sgummalla-works/sketchon — NODE entry point.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The dependency rules are enforced by architecture guard tests
|
|
8
|
-
* (src/application/architecture.test.ts).
|
|
4
|
+
* Re-exports the shared public API (see composition.ts) and binds the
|
|
5
|
+
* disk-backed AssetProvider (bundled Inter fonts + disk-cached Twemoji). This is
|
|
6
|
+
* the default entry for Node + the lab. The browser build is index.browser.ts.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* validateSpec(spec) → ValidationIssue[] (pure, zero deps)
|
|
18
|
-
* selectEngineKey(spec) → EngineKey
|
|
19
|
-
* selectEngine(spec) → Technique
|
|
20
|
-
* TECHNIQUES → all registered engines (for the lab)
|
|
8
|
+
* ── STABLE PUBLIC API (shared by both entries) ───────────────────────────────
|
|
9
|
+
* renderDiagram(spec) → SVG + metadata (auto-routes engine)
|
|
10
|
+
* validateSpec(spec) → ValidationIssue[] (pure, zero deps)
|
|
11
|
+
* selectEngineKey(spec) → EngineKey
|
|
12
|
+
* selectEngine(spec) → Technique
|
|
13
|
+
* configureAssets(over) → override fonts/emoji (dependency injection)
|
|
14
|
+
* TECHNIQUES → all registered engines (for the lab)
|
|
21
15
|
* DiagramSpec + all spec types
|
|
22
16
|
*/
|
|
23
|
-
export * from './
|
|
24
|
-
export * from './domain/validate.js';
|
|
25
|
-
export * from './domain/theme.js';
|
|
26
|
-
export type { Technique, RenderResult, PlacedBox, PlacedEdge, StructuralFeatures, } from './ports/Technique.js';
|
|
27
|
-
export { TechniqueRegistry } from './application/registry.js';
|
|
28
|
-
export { type EngineKey } from './application/router.js';
|
|
29
|
-
export * from './constants.js';
|
|
30
|
-
export { esc, estimateTextWidth, wrapText, palette, PALETTE, arrowDefs, svgDocument, } from './adapters/svg.js';
|
|
17
|
+
export * from './composition.js';
|
|
31
18
|
export { loadFonts } from './adapters/fonts.js';
|
|
32
|
-
export { emojiToDataUri
|
|
33
|
-
export { satoriTechnique } from './adapters/satori.js';
|
|
34
|
-
export { elkTechnique } from './adapters/elk.js';
|
|
35
|
-
export { sequenceTechnique } from './adapters/sequence.js';
|
|
36
|
-
export { baselineTechnique } from './adapters/baseline.js';
|
|
37
|
-
import { TechniqueRegistry } from './application/registry.js';
|
|
38
|
-
/**
|
|
39
|
-
* The application-wide registry. Pre-populated with all built-in engines.
|
|
40
|
-
* Consumers may call `.register()` to add custom engines.
|
|
41
|
-
*/
|
|
42
|
-
export declare const REGISTRY: TechniqueRegistry;
|
|
43
|
-
/** All registered techniques — used by the lab harness. */
|
|
44
|
-
export declare const TECHNIQUES: import("./ports/Technique.js").Technique[];
|
|
45
|
-
/**
|
|
46
|
-
* Select the engine key that would render a spec.
|
|
47
|
-
* Useful for logging / debugging which engine was chosen.
|
|
48
|
-
*/
|
|
49
|
-
export declare const selectEngineKey: (spec: import("./domain/spec.js").DiagramSpec) => import("./application/router.js").EngineKey;
|
|
50
|
-
/**
|
|
51
|
-
* Resolve the Technique that will render a spec.
|
|
52
|
-
*/
|
|
53
|
-
export declare const selectEngine: (spec: import("./domain/spec.js").DiagramSpec) => import("./ports/Technique.js").Technique;
|
|
54
|
-
/**
|
|
55
|
-
* Production render entry point.
|
|
56
|
-
* Validates routing and delegates to the chosen layout engine.
|
|
57
|
-
*
|
|
58
|
-
* @param spec the coordinate-free diagram spec
|
|
59
|
-
* @returns the rendered SVG + width/height/metadata
|
|
60
|
-
*/
|
|
61
|
-
export declare const renderDiagram: (spec: import("./domain/spec.js").DiagramSpec) => import("./ports/Technique.js").RenderResult | Promise<import("./ports/Technique.js").RenderResult>;
|
|
19
|
+
export { emojiToDataUri } from './adapters/emoji.js';
|
|
62
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,83 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @sgummalla-works/sketchon —
|
|
2
|
+
* @sgummalla-works/sketchon — NODE entry point.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The dependency rules are enforced by architecture guard tests
|
|
8
|
-
* (src/application/architecture.test.ts).
|
|
4
|
+
* Re-exports the shared public API (see composition.ts) and binds the
|
|
5
|
+
* disk-backed AssetProvider (bundled Inter fonts + disk-cached Twemoji). This is
|
|
6
|
+
* the default entry for Node + the lab. The browser build is index.browser.ts.
|
|
9
7
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* validateSpec(spec) → ValidationIssue[] (pure, zero deps)
|
|
18
|
-
* selectEngineKey(spec) → EngineKey
|
|
19
|
-
* selectEngine(spec) → Technique
|
|
20
|
-
* TECHNIQUES → all registered engines (for the lab)
|
|
8
|
+
* ── STABLE PUBLIC API (shared by both entries) ───────────────────────────────
|
|
9
|
+
* renderDiagram(spec) → SVG + metadata (auto-routes engine)
|
|
10
|
+
* validateSpec(spec) → ValidationIssue[] (pure, zero deps)
|
|
11
|
+
* selectEngineKey(spec) → EngineKey
|
|
12
|
+
* selectEngine(spec) → Technique
|
|
13
|
+
* configureAssets(over) → override fonts/emoji (dependency injection)
|
|
14
|
+
* TECHNIQUES → all registered engines (for the lab)
|
|
21
15
|
* DiagramSpec + all spec types
|
|
22
16
|
*/
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export * from './domain/validate.js';
|
|
26
|
-
export * from './domain/theme.js';
|
|
27
|
-
// ── Application (registry + router — no adapter imports) ──────────────────────
|
|
28
|
-
export { TechniqueRegistry } from './application/registry.js';
|
|
29
|
-
export {} from './application/router.js';
|
|
30
|
-
// ── Constants + shared render helpers ────────────────────────────────────────
|
|
31
|
-
export * from './constants.js';
|
|
32
|
-
export { esc, estimateTextWidth, wrapText, palette, PALETTE, arrowDefs, svgDocument, } from './adapters/svg.js';
|
|
33
|
-
// ── Node-only loaders (filesystem — not browser-safe) ────────────────────────
|
|
17
|
+
export * from './composition.js';
|
|
18
|
+
// ── Node-only loaders (filesystem — not available in the browser build) ───────
|
|
34
19
|
export { loadFonts } from './adapters/fonts.js';
|
|
35
|
-
export { emojiToDataUri
|
|
36
|
-
// ──
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
export { baselineTechnique } from './adapters/baseline.js';
|
|
41
|
-
// ── COMPOSITION ROOT ──────────────────────────────────────────────────────────
|
|
42
|
-
// Wire all adapters into the registry. This is the only place that is allowed
|
|
43
|
-
// to import adapters. Everything below is infrastructure glue.
|
|
44
|
-
import { TechniqueRegistry } from './application/registry.js';
|
|
45
|
-
import { Router } from './application/router.js';
|
|
46
|
-
import { satoriTechnique } from './adapters/satori.js';
|
|
47
|
-
import { elkTechnique } from './adapters/elk.js';
|
|
48
|
-
import { sequenceTechnique } from './adapters/sequence.js';
|
|
49
|
-
import { baselineTechnique } from './adapters/baseline.js';
|
|
50
|
-
/**
|
|
51
|
-
* The application-wide registry. Pre-populated with all built-in engines.
|
|
52
|
-
* Consumers may call `.register()` to add custom engines.
|
|
53
|
-
*/
|
|
54
|
-
export const REGISTRY = new TechniqueRegistry()
|
|
55
|
-
.register('baseline', baselineTechnique)
|
|
56
|
-
.register('satori', satoriTechnique)
|
|
57
|
-
.register('elk', elkTechnique)
|
|
58
|
-
.register('sequence', sequenceTechnique);
|
|
59
|
-
/**
|
|
60
|
-
* The application-wide router, wired to the shared registry.
|
|
61
|
-
* Exposes the primary use-case functions as bound methods.
|
|
62
|
-
*/
|
|
63
|
-
const router = new Router(REGISTRY);
|
|
64
|
-
/** All registered techniques — used by the lab harness. */
|
|
65
|
-
export const TECHNIQUES = REGISTRY.techniques();
|
|
66
|
-
/**
|
|
67
|
-
* Select the engine key that would render a spec.
|
|
68
|
-
* Useful for logging / debugging which engine was chosen.
|
|
69
|
-
*/
|
|
70
|
-
export const selectEngineKey = router.selectEngineKey.bind(router);
|
|
71
|
-
/**
|
|
72
|
-
* Resolve the Technique that will render a spec.
|
|
73
|
-
*/
|
|
74
|
-
export const selectEngine = router.selectEngine.bind(router);
|
|
75
|
-
/**
|
|
76
|
-
* Production render entry point.
|
|
77
|
-
* Validates routing and delegates to the chosen layout engine.
|
|
78
|
-
*
|
|
79
|
-
* @param spec the coordinate-free diagram spec
|
|
80
|
-
* @returns the rendered SVG + width/height/metadata
|
|
81
|
-
*/
|
|
82
|
-
export const renderDiagram = router.renderDiagram.bind(router);
|
|
20
|
+
export { emojiToDataUri } from './adapters/emoji.js';
|
|
21
|
+
// ── Bind the disk-backed provider as the default for this environment ─────────
|
|
22
|
+
import { setAssetProvider } from './adapters/assets.js';
|
|
23
|
+
import { nodeAssetProvider } from './adapters/assets.node.js';
|
|
24
|
+
setAssetProvider(nodeAssetProvider);
|
|
83
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,cAAc,kBAAkB,CAAC;AAEjC,iFAAiF;AACjF,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,iFAAiF;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,gBAAgB,CAAC,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AssetProvider — the port through which the Satori engine obtains the binary
|
|
3
|
+
* assets it cannot compute: font faces and emoji images.
|
|
4
|
+
*
|
|
5
|
+
* Satori has no filesystem and no font access of its own, so SOMETHING must
|
|
6
|
+
* hand it font bytes and resolve each emoji grapheme to an image. WHERE those
|
|
7
|
+
* bytes come from differs by environment — Node reads them off disk, the
|
|
8
|
+
* browser fetches them — so the source is inverted behind this interface and
|
|
9
|
+
* bound by the composition root (dependency inversion). Consumers may override
|
|
10
|
+
* it via `configureAssets` to supply their own fonts or emoji resolver (e.g. a
|
|
11
|
+
* bundled, fully-offline font set).
|
|
12
|
+
*/
|
|
13
|
+
/** A font face handed to Satori. `data` is the raw font-file bytes. */
|
|
14
|
+
export interface SketchonFont {
|
|
15
|
+
/** Font-family name referenced by the rendered CSS (always "Inter" today). */
|
|
16
|
+
name: string;
|
|
17
|
+
/** Raw font bytes — ttf/otf/woff. NOT woff2 (Satori cannot decode it). */
|
|
18
|
+
data: ArrayBuffer | Uint8Array;
|
|
19
|
+
/** Weight this face provides. */
|
|
20
|
+
weight: 400 | 600 | 700;
|
|
21
|
+
/** Style this face provides. */
|
|
22
|
+
style: 'normal';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Supplies the fonts + emoji images the Satori engine needs. Bound per
|
|
26
|
+
* environment by the composition root; overridable by consumers.
|
|
27
|
+
*/
|
|
28
|
+
export interface AssetProvider {
|
|
29
|
+
/**
|
|
30
|
+
* Load the font faces Satori renders text with.
|
|
31
|
+
*
|
|
32
|
+
* @returns the font faces — synchronous in Node (disk), async in the browser
|
|
33
|
+
* (fetch).
|
|
34
|
+
*/
|
|
35
|
+
loadFonts(): SketchonFont[] | Promise<SketchonFont[]>;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve a single emoji grapheme to an image data-URI for Satori.
|
|
38
|
+
*
|
|
39
|
+
* @param emoji a single emoji grapheme (e.g. "🔍").
|
|
40
|
+
* @returns an `image/svg+xml` data-URI, or a transparent pixel if the emoji
|
|
41
|
+
* cannot be resolved (offline / 404).
|
|
42
|
+
*/
|
|
43
|
+
emojiToDataUri(emoji: string): string | Promise<string>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=AssetProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetProvider.d.ts","sourceRoot":"","sources":["../../src/ports/AssetProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uEAAuE;AACvE,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC;IAC/B,iCAAiC;IACjC,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACxB,gCAAgC;IAChC,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;OAKG;IACH,SAAS,IAAI,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEtD;;;;;;OAMG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AssetProvider — the port through which the Satori engine obtains the binary
|
|
3
|
+
* assets it cannot compute: font faces and emoji images.
|
|
4
|
+
*
|
|
5
|
+
* Satori has no filesystem and no font access of its own, so SOMETHING must
|
|
6
|
+
* hand it font bytes and resolve each emoji grapheme to an image. WHERE those
|
|
7
|
+
* bytes come from differs by environment — Node reads them off disk, the
|
|
8
|
+
* browser fetches them — so the source is inverted behind this interface and
|
|
9
|
+
* bound by the composition root (dependency inversion). Consumers may override
|
|
10
|
+
* it via `configureAssets` to supply their own fonts or emoji resolver (e.g. a
|
|
11
|
+
* bundled, fully-offline font set).
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=AssetProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AssetProvider.js","sourceRoot":"","sources":["../../src/ports/AssetProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sgummalla-works/sketchon",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Sketchon — coordinate-free diagram rendering. A model authors the spec; a deterministic engine computes every pixel. Spec in, SVG out.",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Sketchon — coordinate-free diagram rendering. A model authors the spec; a deterministic engine computes every pixel. Spec in, SVG out. Runs in Node and the browser.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
-
"
|
|
10
|
-
|
|
9
|
+
"browser": {
|
|
10
|
+
"types": "./dist/index.browser.d.ts",
|
|
11
|
+
"default": "./dist/index.browser.js"
|
|
12
|
+
},
|
|
13
|
+
"node": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"default": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
11
21
|
}
|
|
12
22
|
},
|
|
13
23
|
"main": "./dist/index.js",
|
|
24
|
+
"browser": "./dist/index.browser.js",
|
|
25
|
+
"module": "./dist/index.js",
|
|
14
26
|
"types": "./dist/index.d.ts",
|
|
15
27
|
"files": [
|
|
16
28
|
"dist/",
|