@drawmotive/textgraph 0.2.1 → 0.2.2-alpha.1

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 (40) hide show
  1. package/README.md +175 -80
  2. package/docs/api-v1.md +44 -4
  3. package/docs/images/README.md +28 -0
  4. package/docs/images/service-flow.png +0 -0
  5. package/docs/react.md +1 -1
  6. package/docs/releases.md +34 -16
  7. package/examples/service-flow.textgraph +6 -0
  8. package/generated/wasm/DrawMotive.TextGraph.Bridge.wasm +0 -0
  9. package/generated/wasm/ExCSS.wasm +0 -0
  10. package/generated/wasm/Graphics.Core.wasm +0 -0
  11. package/generated/wasm/Grpc.Core.Api.wasm +0 -0
  12. package/generated/wasm/HarfBuzzSharp.wasm +0 -0
  13. package/generated/wasm/Math.Core.wasm +0 -0
  14. package/generated/wasm/Microsoft.Extensions.Logging.Abstractions.wasm +0 -0
  15. package/generated/wasm/NotoSans-Regular.ttf +0 -0
  16. package/generated/wasm/Polly.Core.wasm +0 -0
  17. package/generated/wasm/RBush.wasm +0 -0
  18. package/generated/wasm/SkiaSharp.wasm +0 -0
  19. package/generated/wasm/System.Linq.wasm +0 -0
  20. package/generated/wasm/System.Memory.wasm +0 -0
  21. package/generated/wasm/System.Private.CoreLib.wasm +0 -0
  22. package/generated/wasm/System.Runtime.wasm +0 -0
  23. package/generated/wasm/System.Text.Json.wasm +0 -0
  24. package/generated/wasm/System.Text.RegularExpressions.wasm +0 -0
  25. package/generated/wasm/dotnet.boot.js +22 -17
  26. package/generated/wasm/dotnet.native.js +2 -2
  27. package/generated/wasm/dotnet.native.wasm +0 -0
  28. package/generated/wasm/themes.css +25 -12
  29. package/generated/wasm-manifest.js +44 -37
  30. package/generated/wasm-manifest.json +44 -37
  31. package/package.json +15 -3
  32. package/src/index.d.ts +17 -1
  33. package/src/index.js +2 -2
  34. package/src/platform/node.js +17 -1
  35. package/src/runtime/browser.js +4 -5
  36. package/src/runtime/dotnet.js +7 -5
  37. package/src/runtime/font-resources.js +148 -0
  38. package/src/runtime/language-packs.js +32 -1
  39. package/src/runtime/render-resources.js +13 -12
  40. package/src/runtime/rendering.js +3 -2
package/README.md CHANGED
@@ -1,140 +1,235 @@
1
- # TextGraph SDK
1
+ # TextGraph
2
2
 
3
- Render TextGraph diagrams as PNG images and validate diagram source.
3
+ **Turn text into diagrams in your application.**
4
4
 
5
- > **[Report all TextGraph issues on GitHub →](https://github.com/drawmotive/textgraph/issues)**
6
- > Bugs, feature requests, documentation, playground, SDK, fonts, Markdown, and VS Code issues all belong in this shared tracker.
5
+ Render flowcharts and directed graphs as PNGs in Node.js, browsers, React, and Web
6
+ Workers. TextGraph handles automatic layout and provides source validation and
7
+ rendering diagnostics. The renderer runs where your code runs; no hosted rendering
8
+ API or API key is required.
7
9
 
8
- ## Installation
10
+ [Documentation](https://textgraph.dev/diagrams/flowcharts) ·
11
+ [Runnable examples](https://github.com/drawmotive/textgraph/tree/main/samples) ·
12
+ [API reference](https://github.com/drawmotive/textgraph/blob/main/docs/api-v1.md)
13
+
14
+ ## A few lines. A diagram.
15
+
16
+ ```textgraph
17
+ (horizontal)
18
+ browser -> api -> database
19
+
20
+ browser: Browser
21
+ api(fill primary): API Gateway
22
+ database: Database
23
+ ```
24
+
25
+ ![TextGraph output: Browser connects to API Gateway, which connects to Database.](https://raw.githubusercontent.com/drawmotive/textgraph/main/docs/images/service-flow.png)
26
+
27
+ **[Edit this exact diagram in the playground →](https://textgraph.dev/playground#source=%28horizontal%29%0Abrowser%20-%3E%20api%20-%3E%20database%0A%0Abrowser%3A%20Browser%0Aapi%28fill%20primary%29%3A%20API%20Gateway%0Adatabase%3A%20Database%0A)**
28
+
29
+ Actual SDK output from
30
+ [service-flow.textgraph](https://github.com/drawmotive/textgraph/blob/main/examples/service-flow.textgraph).
31
+ Keep source in version control and render again when relationships change.
32
+ TextGraph uses a small, structured language; it does not interpret unrestricted prose.
33
+
34
+ ## Choose your workflow
35
+
36
+ | What you want to do | Use | Working example |
37
+ | --- | --- | --- |
38
+ | Generate diagrams for documentation, reports, or build jobs | Node.js: write PNG bytes to a file | [Node sample](https://github.com/drawmotive/textgraph/tree/main/samples/node) |
39
+ | Embed live diagrams in dashboards or internal tools | React component and shared provider | [React + Vite sample](https://github.com/drawmotive/textgraph/tree/main/samples/react-vite) |
40
+ | Add editable source and previews to a web app | Browser SDK | [Plain JavaScript sample](https://github.com/drawmotive/textgraph/tree/main/samples/browser) |
41
+ | Keep the UI responsive while rendering larger diagrams | SDK in a module Web Worker | [Worker sample](https://github.com/drawmotive/textgraph/tree/main/samples/worker) |
42
+ | Check syntax and references before rendering | The SDK's `validate()` method | [Validation example](https://github.com/drawmotive/textgraph/blob/main/examples/node.mjs) |
43
+
44
+ For existing documentation, use the
45
+ [Markdown/VitePress plugin](https://textgraph.dev/integrations/markdown) or
46
+ [VS Code Markdown extension](https://textgraph.dev/integrations/vscode).
47
+
48
+ ## Install
9
49
 
10
50
  ```bash
11
- npm install @drawmotive/textgraph@0.2.1
51
+ npm install @drawmotive/textgraph@0.2.2-alpha.1
12
52
  ```
13
53
 
14
- Requires Node.js 22+ or a modern browser.
54
+ Requires **Node.js 22+** or a modern browser with WebAssembly and Web Crypto.
55
+ Browser applications need HTTPS or localhost. React support is an optional entry
56
+ in this package, compatible with React 18.2+ and 19.
15
57
 
16
- Version `0.2.1` defaults React PNG rendering to scale `1`, matching the base SDK. Version `0.2.0` was the first stable release. The exact installation command above becomes available after `0.2.1` is published; `@latest` selects the current published stable release.
58
+ ## Render a PNG in Node.js
17
59
 
18
- ## Quickstart
60
+ Save as `render.mjs`, then run `node render.mjs`:
19
61
 
20
- ```typescript
62
+ ```javascript
21
63
  import { writeFile } from "node:fs/promises";
22
- import { initializeTextGraph } from "@drawmotive/textgraph";
64
+ import { initializeTextGraph } from "@drawmotive/textgraph/node";
23
65
 
24
66
  const textgraph = await initializeTextGraph();
25
-
26
67
  try {
27
- const result = await textgraph.renderPng("A -> B");
28
-
68
+ const result = await textgraph.renderPng("browser -> api -> database");
29
69
  if (result.success) {
30
70
  await writeFile("diagram.png", result.png);
71
+ console.log("Saved diagram.png");
31
72
  } else {
32
- console.log(result.diagnostics);
73
+ console.error(result.diagnostics);
74
+ process.exitCode = 1;
33
75
  }
34
76
  } finally {
35
77
  await textgraph.dispose();
36
78
  }
37
79
  ```
38
80
 
39
- PNG output defaults to bytes, scale `1`, padding `10`, and a white background. Reuse an instance for multiple diagrams, then call `dispose()`.
81
+ Node reads the included runtime from the installed package. No browser, .NET
82
+ installation, or asset-copy step is needed. Reuse an initialized instance for
83
+ multiple diagrams, then dispose it when the job is finished.
40
84
 
41
- ## Higher resolution
42
-
43
- ```typescript
44
- const result = await textgraph.renderPng("A -> B", {
45
- scale: 4,
46
- padding: 24,
47
- });
48
- ```
85
+ [Complete file-to-PNG sample →](https://github.com/drawmotive/textgraph/tree/main/samples/node)
49
86
 
50
- ## Display in a browser
87
+ ## Add a diagram to React
51
88
 
52
- For a bundled application, copy the runtime into its public directory before development or build:
89
+ For browser, React, and Worker applications, copy the runtime assets before
90
+ starting development or building:
53
91
 
54
92
  ```bash
55
93
  npx textgraph-copy-assets public/textgraph/wasm
56
94
  ```
57
95
 
58
- The copy command and React entry below are available starting with `0.2.0`. The [repository samples](https://github.com/drawmotive/textgraph/tree/main/samples) install and run the SDK as a tarball.
96
+ Then render a component:
97
+
98
+ ```tsx
99
+ import { TextGraph, TextGraphProvider } from "@drawmotive/textgraph/react";
100
+ import type { TextGraphInitializeOptions } from "@drawmotive/textgraph";
101
+
102
+ const options: TextGraphInitializeOptions = {
103
+ resolveAsset: (asset) => new URL(`/textgraph/${asset.path}`, location.origin),
104
+ };
105
+
106
+ export function Diagram({ source }: { source: string }) {
107
+ return (
108
+ <TextGraphProvider options={options}>
109
+ <TextGraph source={source} alt="Service dependencies" />
110
+ </TextGraphProvider>
111
+ );
112
+ }
113
+ ```
114
+
115
+ Changing `source` updates the image. For several diagrams, put one provider
116
+ around their common parent. Loading states and rendering diagnostics are built in.
117
+ The component renders on the main thread; use the Worker sample for heavier
118
+ interactive workloads.
119
+
120
+ [React + Vite sample →](https://github.com/drawmotive/textgraph/tree/main/samples/react-vite) ·
121
+ [React guide →](https://github.com/drawmotive/textgraph/blob/main/docs/react.md)
122
+
123
+ ## Render in a browser
59
124
 
60
- ```typescript
125
+ After copying assets as shown above, use this in a bundled browser application:
126
+
127
+ ```javascript
61
128
  import { initializeTextGraph } from "@drawmotive/textgraph/browser";
62
129
 
63
130
  const textgraph = await initializeTextGraph({
64
131
  resolveAsset: (asset) => new URL(`/textgraph/${asset.path}`, location.origin),
65
132
  });
66
- const result = await textgraph.renderPng("A -> B", {
67
- encoding: "base64",
68
- scale: 2,
69
- maxWidth: 1200,
70
- });
71
-
72
- if (result.success) {
73
- const image = document.createElement("img");
74
- image.src = `data:image/png;base64,${result.png}`;
75
- image.alt = "A connects to B";
76
- image.width = result.displayWidth ?? result.width / 2;
77
- image.height = result.displayHeight ?? result.height / 2;
78
- image.style.maxWidth = "100%";
79
- image.style.height = "auto";
80
- document.body.append(image);
133
+ try {
134
+ const result = await textgraph.renderPng("browser -> api -> database", {
135
+ encoding: "base64",
136
+ scale: 2,
137
+ });
138
+ if (result.success) {
139
+ const image = document.createElement("img");
140
+ image.src = `data:image/png;base64,${result.png}`;
141
+ image.alt = "Browser connects to API, which connects to database";
142
+ image.width = result.displayWidth ?? result.width / 2;
143
+ image.height = result.displayHeight ?? result.height / 2;
144
+ image.style.maxWidth = "100%";
145
+ image.style.height = "auto";
146
+ document.body.append(image);
147
+ } else {
148
+ console.error(result.diagnostics);
149
+ }
150
+ } finally {
151
+ await textgraph.dispose();
81
152
  }
82
-
83
- await textgraph.dispose();
84
153
  ```
85
154
 
86
- Scale `2` supplies more pixels for sharper web images; `displayWidth` and `displayHeight` keep the diagram at its logical size, including when `maxWidth` lowers the raster density. PNG DPI metadata does not control its CSS size. Older runtimes omit display dimensions; dividing pixel dimensions by the requested scale is a fallback that cannot recover logical size after `maxWidth` clamps the output.
155
+ For repeated edits, keep the runtime alive and dispose it when the editor closes.
156
+ An async call still computes on its current thread; the Worker sample moves
157
+ rendering off the UI thread.
87
158
 
88
- The npm package includes WASM, .NET runtime modules, fonts, and themes. Bundlers do not automatically deploy these dynamically loaded files. Re-copy assets after SDK updates and use an asset URL matching your deployment base path. Node loads assets from the installed package without this copy step.
159
+ [Browser example →](https://github.com/drawmotive/textgraph/tree/main/samples/browser) ·
160
+ [Worker example →](https://github.com/drawmotive/textgraph/tree/main/samples/worker)
89
161
 
90
- ## React
162
+ ### Deploy the browser runtime
91
163
 
92
- React 18.2+ and 19 use the same SDK through an optional entry; non-React users do not need React. Configure assets once and pass DSL to `TextGraph`:
164
+ - Add the asset-copy command to your application's `predev` and `prebuild` scripts.
165
+ - Deploy the complete copied directory: WASM, JavaScript, fonts, themes, and
166
+ licenses. Re-copy after SDK updates; keep SDK and runtime versions matched.
167
+ - The resolver above assumes hosting at `/`. For a subdirectory, use your deployed
168
+ base path; the Vite samples demonstrate `import.meta.env.BASE_URL`.
93
169
 
94
- ```tsx
95
- import { TextGraph, TextGraphProvider } from "@drawmotive/textgraph/react";
170
+ [Asset hosting and CSP →](https://github.com/drawmotive/textgraph/blob/main/docs/api-v1.md#assets-csp-and-offline-operation)
96
171
 
97
- const options = {
98
- resolveAsset: (asset) => new URL(`/textgraph/${asset.path}`, location.origin),
99
- };
172
+ ## Validation and output options
100
173
 
101
- export function App() {
102
- return (
103
- <TextGraphProvider options={options}>
104
- <TextGraph source={"A -> B"} alt="Flow diagram" />
105
- </TextGraphProvider>
106
- );
107
- }
174
+ On an initialized instance:
175
+
176
+ ```javascript
177
+ const validation = await textgraph.validate("browser -> api -> database");
178
+ console.log(validation.valid, validation.diagnostics);
179
+
180
+ const image = await textgraph.renderPng("browser -> api -> database", {
181
+ scale: 2,
182
+ padding: 24,
183
+ maxWidth: 1200,
184
+ });
108
185
  ```
109
186
 
110
- The component defaults to scale `1`, displays at logical size, and shrinks to fit its container. Set `scale: 2` explicitly for higher raster density. Changing `source` updates the image. The provider shares one lazy runtime across diagrams and disposes it on unmount. See [React integration](docs/react.md) for loading, errors, rendering options, and server rendering.
187
+ Validation checks parsing and semantic references; rendering additionally checks
188
+ layout and output. Diagram failures return diagnostics. Operational failures
189
+ reject with `DrawMotiveError`.
111
190
 
112
- ## Runnable samples
191
+ PNG output defaults to bytes, scale `1`, padding `10`, and a white background.
192
+ Use higher scale for more pixels and returned display dimensions for web sizing.
193
+ TypeScript declarations are included for every public entry point.
113
194
 
114
- The [samples directory](https://github.com/drawmotive/textgraph/tree/main/samples) contains browser JavaScript, React/Vite, Web Worker, and Node applications. Each installs a packed SDK and includes complete run instructions. Samples stay in the repository and are excluded from npm.
195
+ [Full API and options →](https://github.com/drawmotive/textgraph/blob/main/docs/api-v1.md)
115
196
 
116
- ## Additional languages
197
+ ## Run the examples locally
117
198
 
118
- All optional fonts share the `@drawmotive/textgraph-fonts` package, which is not yet published. Select the language descriptors needed by the application; `zhCN` provides Simplified Chinese coverage.
199
+ Samples are complete applications in the public repository and use a local
200
+ package tarball. To try the React sample from a fresh checkout:
119
201
 
120
202
  ```bash
121
- npm install @drawmotive/textgraph-fonts
203
+ git clone https://github.com/drawmotive/textgraph.git
204
+ cd textgraph
205
+ node samples/prepare.mjs react-vite
206
+ cd samples/react-vite
207
+ npm run dev
122
208
  ```
123
209
 
124
- ```typescript
125
- import { initializeTextGraph } from "@drawmotive/textgraph";
126
- import { zhCN } from "@drawmotive/textgraph-fonts";
210
+ Vite samples require Node.js **22.12+**. Replace `react-vite` with `browser` or
211
+ `worker` for those samples. The Node sample uses `npm start` instead.
212
+ Preparation packages the checkout and installs sample dependencies; it does not
213
+ publish anything. Samples are not included in the npm package.
127
214
 
128
- const textgraph = await initializeTextGraph({ languagePacks: [zhCN] });
129
- const result = await textgraph.renderPng("A: 开始\nB: 完成\nA -> B");
130
- await textgraph.dispose();
131
- ```
215
+ [Sample setup and deployment →](https://github.com/drawmotive/textgraph/blob/main/samples/README.md)
132
216
 
133
- ## Validation
217
+ ## Current scope
134
218
 
135
- ```typescript
136
- const result = await textgraph.validate("A -> B");
137
- console.log(result.valid, result.diagnostics);
138
- ```
219
+ - **Available:** flowcharts and directed graphs, automatic layout, PNG rendering,
220
+ and source validation.
221
+ - **Not available yet:** mind maps, sequence diagrams, slides, and SVG export.
222
+ - **Fonts:** Noto Sans and Fuzzy Bubbles are included. Custom font descriptors are
223
+ supported; the optional `@drawmotive/textgraph-fonts` package is not published.
224
+ See [font configuration](https://github.com/drawmotive/textgraph/blob/main/docs/api-v1.md#fonts-and-language-packs).
225
+
226
+ ## Project links
227
+
228
+ [Language guide](https://textgraph.dev/diagrams/flowcharts) ·
229
+ [Changelog](https://github.com/drawmotive/textgraph/blob/main/CHANGELOG.md) ·
230
+ [Report an issue](https://github.com/drawmotive/textgraph/issues) ·
231
+ [MIT license](https://github.com/drawmotive/textgraph/blob/main/LICENSE)
232
+
233
+ ### Try it in a browser
139
234
 
140
- Diagram errors return diagnostics. Operational errors throw `DrawMotiveError`. See the [API reference](docs/api-v1.md) for options, cancellation, and deployment.
235
+ [Open the runnable HTML/JavaScript example](https://textgraph.dev/examples/textgraph/) to edit source, see its PNG and copy the integration code without installing anything. For visual editing, see [the DrawMotive editor](https://textgraph.dev/editor/).
package/docs/api-v1.md CHANGED
@@ -40,11 +40,42 @@ After applying `maxWidth`, output is limited to 16,384 pixels per side and 16,77
40
40
 
41
41
  ## Fonts and language packs
42
42
 
43
+ Runtimes advertising `textgraph-fonts-v1` prepare actual visible labels before measurement.
44
+ Official Chinese, Japanese and emoji fonts load only when needed, then remain decoded
45
+ until the instance is disposed. Node discovers an installed `@drawmotive/textgraph-fonts`
46
+ package automatically; browser hosts copy its assets and supply their deployed catalog:
47
+
48
+ ```javascript
49
+ const runtime = await initializeTextGraph({
50
+ fontAssets: { catalog: new URL("/textgraph/fonts/font-catalog.json", location.origin), fallback: false },
51
+ });
52
+ ```
53
+
54
+ `fontAssets.catalog` is authoritative: missing or corrupt files fail without silently
55
+ switching versions. With no catalog or language packs, fonts are resolved on demand
56
+ from `https://staging.drawmotive.com/static/font-catalog.json`. Set `fallback: false`
57
+ to prohibit that external access, or supply another catalog URL as `fallback`.
58
+ Installing a local package takes precedence over fallback even in offline mode.
59
+ Use `languagePacks: []` with `fallback: false` to explicitly disable automatic font sources.
60
+
61
+ Catalog fonts carry actual Unicode coverage, language hints, byte sizes and SHA-256.
62
+ They are verified before native installation. Catalog URLs are cached per instance;
63
+ HTTP font URLs include the content hash as a stable `v` parameter. HTTP caching remains
64
+ browser/server-owned; there is no new IndexedDB or Service Worker. Offline operation
65
+ requires the complete runtime and font package on a local filesystem or local server;
66
+ an online page cannot fetch an uncached font after losing network access.
67
+
68
+ `renderPng(source, { language: "ja" })` can disambiguate Han-only labels. Without a hint,
69
+ kana selects Japanese for that label and Han-only labels use Chinese. Grapheme-aware
70
+ emoji selection includes flags, ZWJ sequences, modifiers and keycaps. Font selection
71
+ does not depend on which languages were rendered previously. Unsupported glyphs still
72
+ produce font diagnostics; the font catalog defines coverage, not support for every language.
73
+
43
74
  Default rendering includes Noto Sans and Fuzzy Bubbles. Configure additional fonts with `initializeTextGraph({ languagePacks: [...] })`. A `TextGraphLanguagePack` has a non-empty `fonts` array of `{ family, source }` and optional ordered `fallbackFamilies`. Font sources are `URL` objects or non-empty `Uint8Array` values. In Node, use `pathToFileURL()` for filesystem paths; relative asset modules can use `new URL("./font.ttf", import.meta.url)` across platforms.
44
75
 
45
- The initializer copies byte arrays, URLs and descriptor arrays before asynchronous work, so later caller mutations cannot change rendering resources. Families must be unique across all packs and bundled defaults. Fallback families must name configured fonts. Descriptor validation performs no font I/O. Font contents are loaded and configured on first render; validate-only use does not read fonts or themes. Font-loading or configuration failures reject with `DrawMotiveError`; a later render can retry.
76
+ The initializer copies byte arrays, URLs and descriptor arrays before asynchronous work, so later caller mutations cannot change rendering resources. Families must be unique across all packs and bundled defaults. Fallback families must name configured fonts. Descriptor validation performs no font I/O. Legacy descriptors without coverage load on first render; official descriptors carry coverage, languages, bytes and SHA-256 and load on demand. Validate-only use does not read fonts or themes. Font-loading or configuration failures reject with `DrawMotiveError`; a later render can retry.
46
77
 
47
- Bundled resource URLs use `resolveAsset`. Language-pack sources use their supplied URL directly and the platform data loader, including custom `fetch` or the network adapter for network URLs. All optional fonts share `@drawmotive/textgraph-fonts`, installed separately. It currently exports a `zhCN` descriptor for Simplified Chinese; additional language descriptors will use the same package. The package is not yet published.
78
+ Bundled resource URLs use `resolveAsset`. Language-pack sources use their supplied URL directly and the platform data loader, including custom `fetch` or the network adapter for network URLs. All optional fonts share `@drawmotive/textgraph-fonts`, installed separately. It exports `zhCN`, `ja`, `emoji`, `languagePacks` and `fontCatalogUrl`.
48
79
 
49
80
  ## Lifecycle
50
81
 
@@ -59,7 +90,7 @@ Existing `loadRuntime`, `readonly` and `mutate` hooks remain for development com
59
90
  - Node 22 or later: root or `/node`; runtime modules use installed-package `file:` URLs, data uses `node:fs/promises`. HTTP data can use injected fetch, but Node does not import remote HTTP JavaScript. Node `worker_threads` uses `/node`.
60
91
  - Browser: `/browser` or browser conditional export. Modern Chromium, Firefox and WebKit with WebAssembly, ESM, fetch, BigInt and Web Crypto are tested. HTTPS or localhost is required for Web Crypto. Exact engine versions are pinned by the Playwright lockfile; historical minimum browser versions are not claimed.
61
92
  - Browser module Web Worker: `/worker` inside a host-created Worker; no DOM, window, automatic RPC or Worker pool.
62
- - React 18.2+ or 19: `/react` provides `TextGraph` and `TextGraphProvider` over the browser runtime. See [React integration](react.md). This entry is an unreleased addition after `0.1.0-alpha.1`.
93
+ - React 18.2+ or 19: `/react` provides `TextGraph` and `TextGraphProvider` over the browser runtime. See [React integration](react.md).
63
94
 
64
95
  Root condition precedence is worker/browser/node/default. Explicit entries avoid bundler ambiguity. Browser/Worker source graphs exclude Node imports.
65
96
 
@@ -71,7 +102,9 @@ Keep this selection scoped to the development command. With it absent, package l
71
102
 
72
103
  Defaults resolve relative to the installed module. `resolveAsset(asset, defaultUrl)` may return an absolute URL or URL object for each asset. Deploy the complete `generated/wasm` directory: bundlers must preserve/copy these files and configure the resolver for their deployed location. It covers both JS and data. Instance query parameters isolate mutable .NET ESM state; servers should serve identical module bytes regardless of that query.
73
104
 
74
- `fetch` or `adapters.network.fetch` receives data URLs and the applicable initialization or render signal. JS uses dynamic import, which injected fetch cannot intercept. Offline installations must cache the module graph as well as WASM/data at importable URLs, using a Service Worker or local server. No GitHub Releases download is required.
105
+ `fetch` or `adapters.network.fetch` receives data URLs and the applicable initialization or render signal. Independent startup data assets download concurrently; all must pass integrity checks before native startup. JS uses dynamic import, which injected fetch cannot intercept. Offline installations must cache the module graph as well as WASM/data at importable URLs, using a Service Worker or local server. No GitHub Releases download is required.
106
+
107
+ Browser, Worker and Node entry points share this concurrent startup loader. Markdown integrations using the Node entry point inherit it when upgraded to the fixed SDK; their default asset reads are local files. Publishing an SDK version does not update pinned dependencies or previously bundled extensions: consumers must update their dependency and lockfile, then rebuild and redeploy or repackage. The separate `@drawmotive/editor` package uses Blazor's own concurrent loader.
75
108
 
76
109
  Serve WASM as `application/wasm`, JS as `text/javascript`, and provide applicable CORS headers for cross-origin assets. Same-origin CSP: `default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; connect-src 'self'; worker-src 'self'`. No eval, new Function or DOM script injection is used. Cross-origin isolation and SharedArrayBuffer are not required by this single-threaded runtime.
77
110
 
@@ -83,6 +116,13 @@ DSL failures resolve with diagnostics. Operational errors reject with `DrawMotiv
83
116
 
84
117
  ## ABI and versioning
85
118
 
119
+ The additive `textgraph-fonts-v1` capability adds commands to `Execute`:
120
+ `prepare-fonts` takes `source` and optional `language` and returns visible grapheme
121
+ `fontRuns` with `text`, `language` and `missing`; `install-fonts` atomically appends
122
+ fonts with language metadata; `cancel-prepare` releases interrupted preparation.
123
+ Render commands accept the same language hint. Existing configuration/disposal
124
+ envelopes remain unchanged. The wrapper checks this capability before using a catalog.
125
+
86
126
  ABI 1.0.0 retains GetAbiVersion/GetPackageKind/CountParseDiagnostics and adds GetRuntimeInfo(), Validate(source) and Execute(requestJson) on DrawMotive.TextGraph.Bridge.Program. Info returns JSON `{ abiVersion, packageKind, protocolVersion: 1, capabilities }`; Validate returns `{ protocolVersion: 1, valid, diagnostics }`. Wrappers require `textgraph-validate-v1`; PNG rendering additionally requires `textgraph-render-v1` and the manifest `bridge.execute` export. Legacy validation exports remain supported. This is a managed export/JSON protocol, not a raw WASM pointer ABI.
87
127
 
88
128
  `generated/wasm-manifest.json` is authoritative; its ESM projection avoids JSON-module browser assumptions. Shipped schemas describe the manifest, validation response and rendering response. Manifest schema, ABI, protocol and npm versions are separate. Additive exports use capabilities; incompatible wire changes require a new supported version. npm versions and bundled assets are released together. DSL/file-format versions are not frozen by this milestone.
@@ -0,0 +1,28 @@
1
+ # README preview
2
+
3
+ `service-flow.png` is actual output from the package's bundled renderer, using
4
+ `examples/service-flow.textgraph`. Keep the root README's source block and
5
+ playground link synchronized with that file.
6
+
7
+ Regenerate from the repository root with Node.js 22+:
8
+
9
+ ```bash
10
+ node --input-type=module <<'JS'
11
+ import { readFile, writeFile } from 'node:fs/promises';
12
+ import { initializeTextGraph } from '@drawmotive/textgraph/node';
13
+
14
+ const textgraph = await initializeTextGraph();
15
+ try {
16
+ const source = await readFile('examples/service-flow.textgraph', 'utf8');
17
+ const result = await textgraph.renderPng(source, { scale: 2, padding: 24 });
18
+ if (!result.success) throw new Error(JSON.stringify(result.diagnostics));
19
+ await writeFile('docs/images/service-flow.png', result.png);
20
+ } finally {
21
+ await textgraph.dispose();
22
+ }
23
+ JS
24
+ ```
25
+
26
+ The root README uses an absolute GitHub raw URL so the image works on npm as well
27
+ as GitHub. Push the image and source to the public repository before publishing
28
+ the next npm version; npm refreshes its displayed README on publication.
Binary file
package/docs/react.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # React integration
2
2
 
3
- The `/react` entry is an unreleased addition after `0.1.0-alpha.1`. React is an optional peer dependency (`^18.2.0 || ^19.0.0`); applications without React use the ordinary SDK entries.
3
+ The `/react` entry provides a diagram component and shared runtime provider. React is an optional peer dependency (`^18.2.0 || ^19.0.0`); applications without React use the ordinary SDK entries.
4
4
 
5
5
  ## Browser assets
6
6
 
package/docs/releases.md CHANGED
@@ -4,17 +4,14 @@ Releases are selected deliberately and published by `.github/workflows/release.y
4
4
 
5
5
  ## Channels
6
6
 
7
- | Version | npm dist-tag | Installation |
7
+ | Version | npm dist-tag | Install |
8
8
  | --- | --- | --- |
9
- | `0.1.0-alpha.1` | `alpha` | `npm install @drawmotive/textgraph@alpha` |
10
- | `0.2.0` (published) | `latest` | `npm install @drawmotive/textgraph` |
11
- | `0.2.1` (next target) | `latest` after publication | `npm install @drawmotive/textgraph@0.2.1` after publication |
9
+ | `0.2.1` (stable) | `latest` | `npm install @drawmotive/textgraph@0.2.1` |
10
+ | `0.2.2-alpha.1` (preview) | `alpha` | `npm install @drawmotive/textgraph@0.2.2-alpha.1` |
12
11
 
13
- An exact prerelease version also works: `npm install @drawmotive/textgraph@0.1.0-alpha.1`. npm assigns `latest` on a first publication even when another tag is specified. This default is accepted: `0.1.0-alpha.1` initially owned both `alpha` and `latest`. Subsequent alpha releases update `alpha` and preserve the existing default. A stable release updates `latest`.
12
+ Alpha releases update `alpha` and preserve an existing `latest`. npm may assign `latest` on a package’s first publication even when `alpha` is specified.
14
13
 
15
- No stable release is required before publishing another alpha. The script verifies the existing default and immutable artifact integrity without attempting to delete tags. To graduate an alpha, prepare and publish a new stable version.
16
-
17
- The scripts accept stable SemVer and `X.Y.Z-alpha.N`. Other channels require an explicit release-policy change. The shared optional `@drawmotive/textgraph-fonts` package has its own release lifecycle and is not published by this workflow.
14
+ The scripts accept stable SemVer and `X.Y.Z-alpha.N`. The optional `@drawmotive/textgraph-fonts` package uses the separate fonts workflow described below.
18
15
 
19
16
  ## Account setup
20
17
 
@@ -36,10 +33,10 @@ Trusted publishing requires npm 11.5.1+ and Node.js 22.14.0+. Publication from a
36
33
  Native builds belong to the private DrawMotive repository. Commit native source, resource, and bridge changes first, then run there:
37
34
 
38
35
  ```bash
39
- npm run release:textgraph -- 0.2.1
36
+ npm run release:textgraph -- 0.2.2-alpha.1
40
37
  ```
41
38
 
42
- This updates the package and lock versions, builds Release assets from the recorded private source commit, generates matching JSON/ESM manifests, updates the root workspace lock, and verifies asset hashes. It does not commit, push, tag, or publish. The `just release-textgraph 0.2.1` alias runs the same command.
39
+ This updates the package and lock versions, builds Release assets from the recorded private source commit, generates matching JSON/ESM manifests, updates the root workspace lock, and verifies asset hashes. It does not commit, push, tag, or publish. The `just release-textgraph 0.2.2-alpha.1` alias runs the same command.
43
40
 
44
41
  For a JavaScript-only release reusing already verified native bytes, run in this package:
45
42
 
@@ -83,26 +80,47 @@ If npm requires a one-time code, run with `NPM_CONFIG_OTP` set in the local term
83
80
  After preparation, tests, and review, create the tag on the verified package commit:
84
81
 
85
82
  ```bash
86
- git tag -a textgraph-v0.2.1 -m "Release 0.2.1"
87
- git push origin textgraph-v0.2.1
83
+ git tag -a textgraph-v0.2.2-alpha.1 -m "Release 0.2.2-alpha.1"
84
+ git push origin textgraph-v0.2.2-alpha.1
88
85
  ```
89
86
 
90
- The release workflow resolves the tag to a commit, runs Node.js and three-browser tests on Ubuntu, packs the tested checkout, and passes the artifact to the `npm` environment for publication. All CI and release jobs use `ubuntu-latest`; the browser suite covers Chromium, Firefox, and WebKit. Stable releases select `latest` automatically. Never pass a custom dist-tag to bypass the release policy.
87
+ The release workflow resolves the tag to a commit, runs Node.js and three-browser tests on Ubuntu, packs the tested checkout, and passes the artifact to the `npm` environment for publication. All CI and release jobs use `ubuntu-latest`; the browser suite covers Chromium, Firefox, and WebKit. Alpha releases select `alpha`; stable releases select `latest`. Never pass a custom dist-tag to bypass the release policy.
91
88
 
92
89
  ## Verify publication and recover
93
90
 
94
91
  ```bash
95
92
  npm view @drawmotive/textgraph dist-tags --json
96
- npm view @drawmotive/textgraph@0.2.1 dist.integrity
97
- npm install @drawmotive/textgraph@0.2.1
93
+ npm view @drawmotive/textgraph@0.2.2-alpha.1 dist.integrity
94
+ npm install @drawmotive/textgraph@0.2.2-alpha.1
98
95
  ```
99
96
 
100
97
  If a workflow fails before publishing, fix the configuration and rerun the same tag. For a manual dispatch, select the release tag as the workflow ref and supply the same tag as input; dispatching from `main` is rejected so OIDC and provenance identify the correct commit. For example:
101
98
 
102
99
  ```bash
103
- gh workflow run release.yml --ref textgraph-v0.2.1 -f tag=textgraph-v0.2.1
100
+ gh workflow run release.yml --ref textgraph-v0.2.2-alpha.1 -f tag=textgraph-v0.2.2-alpha.1
104
101
  ```
105
102
 
106
103
  If publication succeeded but a later check failed, the script accepts an identical registry artifact with the correct channel and refuses different bytes at the same version. Keep the original workflow artifact for diagnosing integrity differences.
107
104
 
108
105
  The first alpha owning `latest` is expected and requires no repair. If a later publication unexpectedly changes an existing default, inspect registry state before retrying. Do not unpublish, overwrite versions, or delete tags as a routine recovery step.
106
+
107
+ ## Optional fonts package
108
+
109
+ `.github/workflows/release-fonts.yml` publishes `@drawmotive/textgraph-fonts` from tags named `textgraph-fonts-v<VERSION>`. It verifies the coordinated release target, font hashes, Unicode coverage, pinned provenance, original license/notice hashes, offline installation, and publication policy before packing. The package has no native build or SDK dependency.
110
+
111
+ Run these checks from the TextGraph repository after synchronizing the release target and package/lock versions in the parent repository:
112
+
113
+ ```bash
114
+ npm ci --prefix language-packs --workspaces=false
115
+ npm run build --prefix language-packs --workspaces=false
116
+ npm test --prefix language-packs --workspaces=false
117
+ node --test --test-concurrency=1 test/release.test.mjs test/fonts-release.test.mjs
118
+ node scripts/fonts-release.mjs pack
119
+ node scripts/publish-fonts-release.mjs --dry-run
120
+ ```
121
+
122
+ The exact archive and receipt remain in `language-packs/.release/`; CI retains them as the `textgraph-fonts-npm-release` artifact for 30 days and passes them unchanged to the publish job. Font alpha releases use `alpha`, preserve an existing `latest`, and accept npm assigning `latest` on first publication. A retry verifies the existing version's integrity instead of publishing it again.
123
+
124
+ Allow `textgraph-fonts-v*` tags in the GitHub `npm` environment. For bootstrap, an authorized administrator can set its `NPM_TOKEN` secret to an npm token with permission to create/publish this scoped package. The workflow writes only a token variable reference into a temporary npm configuration; it does not print or retain the credential in the artifact. Once the package exists, configure its trusted publisher with repository `drawmotive/textgraph`, workflow `release-fonts.yml`, and environment `npm`, then remove the bootstrap secret. Without that secret the workflow uses npm trusted publishing with OIDC.
125
+
126
+ After committing and reviewing the release, publish the matching `textgraph-fonts-v<VERSION>` tag. Manual retries must use the same existing tag for both the workflow ref and the `tag` input. Publish the fonts package before refreshing consumer lockfiles; consumers must resolve the actual public registry tarball and integrity.
@@ -0,0 +1,6 @@
1
+ (horizontal)
2
+ browser -> api -> database
3
+
4
+ browser: Browser
5
+ api(fill primary): API Gateway
6
+ database: Database
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file