@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.
Files changed (49) hide show
  1. package/README.md +40 -4
  2. package/dist/adapters/assets.browser.d.ts +4 -0
  3. package/dist/adapters/assets.browser.d.ts.map +1 -0
  4. package/dist/adapters/assets.browser.js +64 -0
  5. package/dist/adapters/assets.browser.js.map +1 -0
  6. package/dist/adapters/assets.d.ts +34 -0
  7. package/dist/adapters/assets.d.ts.map +1 -0
  8. package/dist/adapters/assets.js +36 -0
  9. package/dist/adapters/assets.js.map +1 -0
  10. package/dist/adapters/assets.node.d.ts +4 -0
  11. package/dist/adapters/assets.node.d.ts.map +1 -0
  12. package/dist/adapters/assets.node.js +16 -0
  13. package/dist/adapters/assets.node.js.map +1 -0
  14. package/dist/adapters/emoji-code.d.ts +8 -0
  15. package/dist/adapters/emoji-code.d.ts.map +1 -0
  16. package/dist/adapters/emoji-code.js +41 -0
  17. package/dist/adapters/emoji-code.js.map +1 -0
  18. package/dist/adapters/emoji.d.ts +2 -4
  19. package/dist/adapters/emoji.d.ts.map +1 -1
  20. package/dist/adapters/emoji.js +8 -34
  21. package/dist/adapters/emoji.js.map +1 -1
  22. package/dist/adapters/fonts.d.ts +3 -8
  23. package/dist/adapters/fonts.d.ts.map +1 -1
  24. package/dist/adapters/fonts.js +7 -4
  25. package/dist/adapters/fonts.js.map +1 -1
  26. package/dist/adapters/satori.d.ts.map +1 -1
  27. package/dist/adapters/satori.js +6 -4
  28. package/dist/adapters/satori.js.map +1 -1
  29. package/dist/composition.d.ts +54 -0
  30. package/dist/composition.d.ts.map +1 -0
  31. package/dist/composition.js +68 -0
  32. package/dist/composition.js.map +1 -0
  33. package/dist/constants.d.ts +3 -0
  34. package/dist/constants.d.ts.map +1 -1
  35. package/dist/constants.js +12 -0
  36. package/dist/constants.js.map +1 -1
  37. package/dist/index.browser.d.ts +15 -0
  38. package/dist/index.browser.d.ts.map +1 -0
  39. package/dist/index.browser.js +19 -0
  40. package/dist/index.browser.js.map +1 -0
  41. package/dist/index.d.ts +13 -55
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +18 -76
  44. package/dist/index.js.map +1 -1
  45. package/dist/ports/AssetProvider.d.ts +45 -0
  46. package/dist/ports/AssetProvider.d.ts.map +1 -0
  47. package/dist/ports/AssetProvider.js +14 -0
  48. package/dist/ports/AssetProvider.js.map +1 -0
  49. 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
- | `validateSpec` | Re-exported from `domain/validate.ts`. |
177
- | `loadFonts` | Node-only: loads bundled Inter TTFs for Satori. |
178
- | `emojiToDataUri` | Node-only: resolves an emoji to a Twemoji SVG data-URI. |
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: **75 unit tests** across domain validation, application routing/registry, the adapters, and the architecture guard.
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,4 @@
1
+ import type { AssetProvider } from '../ports/AssetProvider.js';
2
+ /** Fetch-backed provider: CDN fonts + CDN emoji, both cached in memory. */
3
+ export declare const browserAssetProvider: AssetProvider;
4
+ //# sourceMappingURL=assets.browser.d.ts.map
@@ -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,4 @@
1
+ import type { AssetProvider } from '../ports/AssetProvider.js';
2
+ /** Disk-backed provider: bundled fonts, disk-cached emoji. */
3
+ export declare const nodeAssetProvider: AssetProvider;
4
+ //# sourceMappingURL=assets.node.d.ts.map
@@ -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"}
@@ -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":"AA6CA,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG/C;AAID;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BnE"}
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"}
@@ -1,54 +1,28 @@
1
1
  /**
2
- * Emoji rendering for Satori. Satori has no emoji font, so it calls
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
- * Codepoint derivation follows Twemoji's own filename rule: strip the FE0F
9
- * variation selector UNLESS the sequence is a ZWJ join — otherwise the asset
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(`${TWEMOJI_BASE}/${code}.svg`);
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":"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"}
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"}
@@ -1,13 +1,8 @@
1
- export interface SatoriFont {
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(): SatoriFont[];
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":"AAYA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACxB,KAAK,EAAE,QAAQ,CAAC;CACjB;AAID;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,UAAU,EAAE,CAQxC"}
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"}
@@ -1,7 +1,10 @@
1
1
  /**
2
- * Font loading 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 the
4
- * lab is self-contained and runs offline after clone. Loaded once and cached.
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;;;;GAIG;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;AAEzC,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;AASlD,IAAI,MAAM,GAAwB,IAAI,CAAC;AAEvC;;;;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
+ {"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":"AA6BA,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAmRrE,eAAO,MAAM,eAAe,EAAE,SAkC7B,CAAC"}
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"}
@@ -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 { loadFonts } from './fonts.js';
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
- const fonts = loadFonts();
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":"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"}
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"}
@@ -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;
@@ -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;AAKjC,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"}
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."
@@ -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 — public API + COMPOSITION ROOT.
2
+ * @sgummalla-works/sketchon — NODE entry point.
3
3
  *
4
- * ── HEXAGONAL ARCHITECTURE COMPOSITION ROOT RULES ──────────────────────────
5
- * This file is the ONLY place in the package that may import concrete adapters.
6
- * All other application/domain files must be free of adapter imports.
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
- * Dependency flow (all arrows point inward):
11
- * adapters/ ──► application/ ──► domain/
12
- * adapters/ ──► ports/
13
- * index.ts (composition root) wires all layers together.
14
- *
15
- * ── STABLE PUBLIC API ────────────────────────────────────────────────────────
16
- * renderDiagram(spec) SVG + metadata (auto-routes engine)
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 './domain/spec.js';
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, emojiCode } from './adapters/emoji.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
- /**
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;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;AAG9B,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,MAAsB,qBAAqB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGhE,OAAO,EAAE,eAAe,EAAE,MAAQ,sBAAsB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAW,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAK3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAO9D;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAE,iBAImB,CAAC;AAQ3C,2DAA2D;AAC3D,eAAO,MAAM,UAAU,4CAAwB,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,eAAe,+FAAsC,CAAC;AAEnE;;GAEG;AACH,eAAO,MAAM,YAAY,4FAAmC,CAAC;AAE7D;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,sJAAoC,CAAC"}
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 — public API + COMPOSITION ROOT.
2
+ * @sgummalla-works/sketchon — NODE entry point.
3
3
  *
4
- * ── HEXAGONAL ARCHITECTURE COMPOSITION ROOT RULES ──────────────────────────
5
- * This file is the ONLY place in the package that may import concrete adapters.
6
- * All other application/domain files must be free of adapter imports.
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
- * Dependency flow (all arrows point inward):
11
- * adapters/ ──► application/ ──► domain/
12
- * adapters/ ──► ports/
13
- * index.ts (composition root) wires all layers together.
14
- *
15
- * ── STABLE PUBLIC API ────────────────────────────────────────────────────────
16
- * renderDiagram(spec) SVG + metadata (auto-routes engine)
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
- // ── Domain (pure — zero external deps) ───────────────────────────────────────
24
- export * from './domain/spec.js';
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, emojiCode } from './adapters/emoji.js';
36
- // ── Concrete adapters (exported for advanced use + the lab) ───────────────────
37
- export { satoriTechnique } from './adapters/satori.js';
38
- export { elkTechnique } from './adapters/elk.js';
39
- export { sequenceTechnique } from './adapters/sequence.js';
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;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,gFAAgF;AAChF,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAWlC,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,gFAAgF;AAChF,OAAO,EAAE,SAAS,EAAE,MAAsB,qBAAqB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEhE,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAQ,sBAAsB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAW,mBAAmB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,iFAAiF;AACjF,8EAA8E;AAC9E,+DAA+D;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAQ,sBAAsB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAW,mBAAmB,CAAC;AACtD,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,EAAI,eAAe,CAAC;KACrC,QAAQ,CAAC,KAAK,EAAO,YAAY,CAAC;KAClC,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEpC,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC"}
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.1.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
- "import": "./dist/index.js",
10
- "types": "./dist/index.d.ts"
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/",