@drawmotive/textgraph 0.1.0-alpha.1 → 0.2.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 (85) hide show
  1. package/README.md +55 -7
  2. package/docs/api-v1.md +11 -4
  3. package/docs/react.md +55 -0
  4. package/docs/releases.md +23 -15
  5. package/generated/wasm/DrawMotive.TextGraph.Bridge.runtimeconfig.json +1 -1
  6. package/generated/wasm/DrawMotive.TextGraph.Bridge.wasm +0 -0
  7. package/generated/wasm/Graphics.Core.wasm +0 -0
  8. package/generated/wasm/Grpc.Core.Api.wasm +0 -0
  9. package/generated/wasm/HarfBuzzSharp.wasm +0 -0
  10. package/generated/wasm/Math.Core.wasm +0 -0
  11. package/generated/wasm/Microsoft.AspNetCore.Components.Web.wasm +0 -0
  12. package/generated/wasm/Microsoft.Extensions.DependencyInjection.Abstractions.wasm +0 -0
  13. package/generated/wasm/Microsoft.Extensions.DependencyInjection.wasm +0 -0
  14. package/generated/wasm/Microsoft.Extensions.Logging.Abstractions.wasm +0 -0
  15. package/generated/wasm/Microsoft.Extensions.Logging.wasm +0 -0
  16. package/generated/wasm/Microsoft.Extensions.Options.wasm +0 -0
  17. package/generated/wasm/Microsoft.Extensions.Primitives.wasm +0 -0
  18. package/generated/wasm/Polly.Core.wasm +0 -0
  19. package/generated/wasm/RBush.wasm +0 -0
  20. package/generated/wasm/SkiaSharp.HarfBuzz.wasm +0 -0
  21. package/generated/wasm/SkiaSharp.wasm +0 -0
  22. package/generated/wasm/System.Collections.Concurrent.wasm +0 -0
  23. package/generated/wasm/System.Collections.Immutable.wasm +0 -0
  24. package/generated/wasm/System.Collections.NonGeneric.wasm +0 -0
  25. package/generated/wasm/System.Collections.Specialized.wasm +0 -0
  26. package/generated/wasm/System.Collections.wasm +0 -0
  27. package/generated/wasm/System.ComponentModel.Annotations.wasm +0 -0
  28. package/generated/wasm/System.ComponentModel.Primitives.wasm +0 -0
  29. package/generated/wasm/System.ComponentModel.TypeConverter.wasm +0 -0
  30. package/generated/wasm/System.ComponentModel.wasm +0 -0
  31. package/generated/wasm/System.Console.wasm +0 -0
  32. package/generated/wasm/System.Diagnostics.StackTrace.wasm +0 -0
  33. package/generated/wasm/System.Diagnostics.Tracing.wasm +0 -0
  34. package/generated/wasm/System.IO.Compression.Brotli.wasm +0 -0
  35. package/generated/wasm/System.IO.Compression.wasm +0 -0
  36. package/generated/wasm/System.IO.Pipelines.wasm +0 -0
  37. package/generated/wasm/System.Linq.Expressions.wasm +0 -0
  38. package/generated/wasm/System.Linq.wasm +0 -0
  39. package/generated/wasm/System.Memory.wasm +0 -0
  40. package/generated/wasm/System.Net.Http.wasm +0 -0
  41. package/generated/wasm/System.Net.Primitives.wasm +0 -0
  42. package/generated/wasm/System.Numerics.Vectors.wasm +0 -0
  43. package/generated/wasm/System.ObjectModel.wasm +0 -0
  44. package/generated/wasm/System.Private.CoreLib.wasm +0 -0
  45. package/generated/wasm/System.Private.Uri.wasm +0 -0
  46. package/generated/wasm/System.Reflection.Emit.ILGeneration.wasm +0 -0
  47. package/generated/wasm/System.Reflection.Emit.wasm +0 -0
  48. package/generated/wasm/System.Reflection.Primitives.wasm +0 -0
  49. package/generated/wasm/System.Runtime.InteropServices.JavaScript.wasm +0 -0
  50. package/generated/wasm/System.Runtime.InteropServices.wasm +0 -0
  51. package/generated/wasm/System.Runtime.Intrinsics.wasm +0 -0
  52. package/generated/wasm/System.Runtime.Loader.wasm +0 -0
  53. package/generated/wasm/System.Runtime.Numerics.wasm +0 -0
  54. package/generated/wasm/System.Runtime.Serialization.Primitives.wasm +0 -0
  55. package/generated/wasm/System.Runtime.wasm +0 -0
  56. package/generated/wasm/System.Security.Cryptography.wasm +0 -0
  57. package/generated/wasm/System.Text.Encoding.Extensions.wasm +0 -0
  58. package/generated/wasm/System.Text.Encodings.Web.wasm +0 -0
  59. package/generated/wasm/System.Text.Json.wasm +0 -0
  60. package/generated/wasm/System.Text.RegularExpressions.wasm +0 -0
  61. package/generated/wasm/System.Threading.Channels.wasm +0 -0
  62. package/generated/wasm/System.Threading.Thread.wasm +0 -0
  63. package/generated/wasm/System.Threading.ThreadPool.wasm +0 -0
  64. package/generated/wasm/System.Threading.wasm +0 -0
  65. package/generated/wasm/System.wasm +0 -0
  66. package/generated/wasm/dotnet.boot.js +63 -63
  67. package/generated/wasm/dotnet.js +1 -1
  68. package/generated/wasm/dotnet.native.js +745 -22
  69. package/generated/wasm/dotnet.native.wasm +0 -0
  70. package/generated/wasm/dotnet.runtime.js +1 -1
  71. package/generated/wasm/netstandard.wasm +0 -0
  72. package/generated/wasm-manifest.js +78 -78
  73. package/generated/wasm-manifest.json +78 -78
  74. package/package.json +39 -7
  75. package/schemas/render.schema.json +33 -1
  76. package/scripts/copy-assets.mjs +49 -0
  77. package/src/index.d.ts +4 -2
  78. package/src/platform/node.d.ts +2 -0
  79. package/src/platform/node.js +4 -1
  80. package/src/react/index.d.ts +20 -0
  81. package/src/react/index.js +59 -0
  82. package/src/react/runtime.js +37 -0
  83. package/src/runtime/dotnet.js +3 -1
  84. package/src/runtime/node.js +22 -1
  85. package/src/runtime/rendering.js +11 -3
package/README.md CHANGED
@@ -2,15 +2,18 @@
2
2
 
3
3
  Render TextGraph diagrams as PNG images and validate diagram source.
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.
7
+
5
8
  ## Installation
6
9
 
7
10
  ```bash
8
- npm install @drawmotive/textgraph@alpha
11
+ npm install @drawmotive/textgraph@0.2.1
9
12
  ```
10
13
 
11
14
  Requires Node.js 22+ or a modern browser.
12
15
 
13
- Alpha releases require `@alpha` or an exact version such as `@0.1.0-alpha.1`. Once a stable release is available, `npm install @drawmotive/textgraph` installs the stable version.
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.
14
17
 
15
18
  ## Quickstart
16
19
 
@@ -33,7 +36,7 @@ try {
33
36
  }
34
37
  ```
35
38
 
36
- PNG output defaults to bytes, scale `2`, padding `10`, and a white background. Reuse an instance for multiple diagrams, then call `dispose()`.
39
+ PNG output defaults to bytes, scale `1`, padding `10`, and a white background. Reuse an instance for multiple diagrams, then call `dispose()`.
37
40
 
38
41
  ## Higher resolution
39
42
 
@@ -46,12 +49,23 @@ const result = await textgraph.renderPng("A -> B", {
46
49
 
47
50
  ## Display in a browser
48
51
 
52
+ For a bundled application, copy the runtime into its public directory before development or build:
53
+
54
+ ```bash
55
+ npx textgraph-copy-assets public/textgraph/wasm
56
+ ```
57
+
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.
59
+
49
60
  ```typescript
50
61
  import { initializeTextGraph } from "@drawmotive/textgraph/browser";
51
62
 
52
- const textgraph = await initializeTextGraph();
63
+ const textgraph = await initializeTextGraph({
64
+ resolveAsset: (asset) => new URL(`/textgraph/${asset.path}`, location.origin),
65
+ });
53
66
  const result = await textgraph.renderPng("A -> B", {
54
67
  encoding: "base64",
68
+ scale: 2,
55
69
  maxWidth: 1200,
56
70
  });
57
71
 
@@ -59,23 +73,57 @@ if (result.success) {
59
73
  const image = document.createElement("img");
60
74
  image.src = `data:image/png;base64,${result.png}`;
61
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";
62
80
  document.body.append(image);
63
81
  }
64
82
 
65
83
  await textgraph.dispose();
66
84
  ```
67
85
 
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.
87
+
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.
89
+
90
+ ## React
91
+
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`:
93
+
94
+ ```tsx
95
+ import { TextGraph, TextGraphProvider } from "@drawmotive/textgraph/react";
96
+
97
+ const options = {
98
+ resolveAsset: (asset) => new URL(`/textgraph/${asset.path}`, location.origin),
99
+ };
100
+
101
+ export function App() {
102
+ return (
103
+ <TextGraphProvider options={options}>
104
+ <TextGraph source={"A -> B"} alt="Flow diagram" />
105
+ </TextGraphProvider>
106
+ );
107
+ }
108
+ ```
109
+
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.
111
+
112
+ ## Runnable samples
113
+
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.
115
+
68
116
  ## Additional languages
69
117
 
70
- Additional language packages are not yet published.
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.
71
119
 
72
120
  ```bash
73
- npm install @drawmotive/textgraph-fonts-zh-cn
121
+ npm install @drawmotive/textgraph-fonts
74
122
  ```
75
123
 
76
124
  ```typescript
77
125
  import { initializeTextGraph } from "@drawmotive/textgraph";
78
- import { zhCN } from "@drawmotive/textgraph-fonts-zh-cn";
126
+ import { zhCN } from "@drawmotive/textgraph-fonts";
79
127
 
80
128
  const textgraph = await initializeTextGraph({ languagePacks: [zhCN] });
81
129
  const result = await textgraph.renderPng("A: 开始\nB: 完成\nA -> B");
package/docs/api-v1.md CHANGED
@@ -20,12 +20,12 @@ Initialization resolves after manifest and real bridge agree on ABI, protocol an
20
20
 
21
21
  ## PNG rendering
22
22
 
23
- `renderPng(source, options?)` returns `{ success: true, png, width, height, diagnostics }` or `{ success: false, diagnostics }`. Diagram failures resolve with diagnostics and contain no image data. Successful results and diagnostics are frozen; byte output is a detached, caller-owned `Uint8Array`. Output uses a white background.
23
+ `renderPng(source, options?)` returns `{ success: true, png, width, height, displayWidth?, displayHeight?, diagnostics }` or `{ success: false, diagnostics }`. `width` and `height` are raster pixels. The optional display dimensions are positive numbers representing logical size: raster dimensions divided by the effective scale after any `maxWidth` reduction. Older runtimes omit both fields. Diagram failures resolve with diagnostics and contain no image data. Successful results and diagnostics are frozen; byte output is a detached, caller-owned `Uint8Array`. Output uses a white background.
24
24
 
25
25
  | Option | Default | Meaning |
26
26
  | --- | --- | --- |
27
27
  | `encoding` | `"bytes"` | `"bytes"` returns `Uint8Array`; `"base64"` returns a string without a data-URL prefix. |
28
- | `scale` | `2` | Positive finite render scale. |
28
+ | `scale` | `1` | Positive finite raster density relative to logical diagram size. |
29
29
  | `padding` | `10` | Non-negative finite padding in diagram units. |
30
30
  | `maxWidth` | Omitted | Positive safe integer maximum output width in pixels; preserves proportions and only reduces output size. |
31
31
  | `signal` | Omitted | Cancels queued work or discards completed work after cancellation. |
@@ -34,6 +34,8 @@ Literal encodings infer their corresponding PNG type in TypeScript; union encodi
34
34
 
35
35
  Scale and padding must remain finite when represented as 32-bit floats; scale must also remain greater than zero. Invalid arguments reject with `INVALID_ARGUMENT`.
36
36
 
37
+ For web display, use scale `2` and the returned display dimensions as image dimensions, with `max-width: 100%; height: auto`. Increasing density then improves sharpness without enlarging the diagram. DPI metadata does not change CSS sizing. When an older runtime omits display dimensions, dividing raster dimensions by the requested scale works only when `maxWidth` did not reduce the effective density.
38
+
37
39
  After applying `maxWidth`, output is limited to 16,384 pixels per side and 16,777,216 pixels in total. Larger images return the `TG_RENDER_SIZE_LIMIT` diagnostic. PNG dimensions and signature are checked against the response metadata; malformed responses reject with `INVALID_RESPONSE`.
38
40
 
39
41
  ## Fonts and language packs
@@ -42,7 +44,7 @@ Default rendering includes Noto Sans and Fuzzy Bubbles. Configure additional fon
42
44
 
43
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.
44
46
 
45
- 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. `@drawmotive/textgraph-fonts-zh-cn` exports a `zhCN` descriptor for Simplified Chinese. The optional package is installed separately.
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.
46
48
 
47
49
  ## Lifecycle
48
50
 
@@ -57,9 +59,14 @@ Existing `loadRuntime`, `readonly` and `mutate` hooks remain for development com
57
59
  - 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`.
58
60
  - 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.
59
61
  - 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`.
60
63
 
61
64
  Root condition precedence is worker/browser/node/default. Explicit entries avoid bundler ambiguity. Browser/Worker source graphs exclude Node imports.
62
65
 
66
+ The repository development command can set `DRAWMOTIVE_TEXTGRAPH_RUNTIME` to an absolute generated directory for Node and inherited Node Workers. The default Node loader then reads that directory's `wasm-manifest.json` and resolves native modules, fonts, and themes there; existing manifest validation and asset integrity checks still apply. Missing or invalid local artifacts reject initialization or rendering without falling back to packaged assets. A supplied `resolveAsset` receives the selected local URL as its default; an explicit `loadRuntime` remains authoritative. Browser and browser Worker loaders ignore this environment variable.
67
+
68
+ Keep this selection scoped to the development command. With it absent, package loading is unchanged; `info.packageVersion` identifies the JavaScript wrapper and capabilities reflect the intersection of the selected manifest and native bridge. Native manifests marked `privateSource.development: true` are rejected by release verification.
69
+
63
70
  ## Assets, CSP and offline operation
64
71
 
65
72
  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.
@@ -82,6 +89,6 @@ ABI 1.0.0 retains GetAbiVersion/GetPackageKind/CountParseDiagnostics and adds Ge
82
89
 
83
90
  Assets have relative path, media type, byte count and SHA-256. Packaging checks reject missing/extra assets, debug files, hash/projection/version drift. Runtime data assets are hash-checked before native startup. Bundled fonts and themes are loaded and hash-checked lazily before the first render; license files require no runtime I/O. These checks establish distribution consistency, not authenticated runtime signatures. `privateSource.commit` identifies committed private C# and bridge inputs. Toolchain changes may change bytes; cross-toolchain byte-for-byte reproducibility is not promised.
84
91
 
85
- The rendering wire uses one `Execute(requestJson)` export. Configuration is performed once before the first render with `{ protocolVersion: 1, operation: "configure", theme, fonts: [{ family, data }], fallbackFamilies }`, where `data` is base64 font data. Its response is `{ protocolVersion: 1, success, diagnostics }`. A render request is `{ protocolVersion: 1, operation: "render", source, export: { format: "png", scale, padding, maxWidth? } }`. Native success returns base64 `png`, `width`, `height`, and diagnostics; failures contain only `success: false` and diagnostics beside the protocol version. The JavaScript wrapper converts image data to the requested encoding.
92
+ The rendering wire uses one `Execute(requestJson)` export. Configuration is performed once before the first render with `{ protocolVersion: 1, operation: "configure", theme, fonts: [{ family, data }], fallbackFamilies }`, where `data` is base64 font data. Its response is `{ protocolVersion: 1, success, diagnostics }`. A render request is `{ protocolVersion: 1, operation: "render", source, export: { format: "png", scale, padding, maxWidth? } }`. Native success returns base64 `png`, `width`, `height`, and diagnostics, plus an additive optional `displayWidth`/`displayHeight` pair; failures contain only `success: false` and diagnostics beside the protocol version. The JavaScript wrapper validates the display dimensions when present and converts image data to the requested encoding.
86
93
 
87
94
  For rendering-capable bridges, disposal sends `{ protocolVersion: 1, operation: "dispose" }` and validates the same success/diagnostics envelope as configuration. This request releases native resources without loading fonts or shutting down the host runtime. Legacy validation-only bridges release wrapper references directly.
package/docs/react.md ADDED
@@ -0,0 +1,55 @@
1
+ # React integration
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.
4
+
5
+ ## Browser assets
6
+
7
+ Run `textgraph-copy-assets public/textgraph/wasm` in your application after installing the SDK, and again after updates. Put it in `predev` and `prebuild` scripts. Serve the public directory, then resolve assets to that URL:
8
+
9
+ ```tsx
10
+ import { TextGraph, TextGraphProvider } from '@drawmotive/textgraph/react';
11
+ import type { TextGraphInitializeOptions } from '@drawmotive/textgraph';
12
+
13
+ const options: TextGraphInitializeOptions = {
14
+ resolveAsset: asset => new URL(`/textgraph/${asset.path}`, location.origin),
15
+ };
16
+
17
+ export function Diagram({ source }: { source: string }) {
18
+ return (
19
+ <TextGraphProvider options={options}>
20
+ <TextGraph source={source} alt="Process flow"
21
+ renderOptions={{ maxWidth: 1200 }} />
22
+ </TextGraphProvider>
23
+ );
24
+ }
25
+ ```
26
+
27
+ For several diagrams, place a single provider around their common parent. Keep `options` stable using a module constant or `useMemo`; replacing it replaces the runtime, for example when changing language packs. Startup occurs only when a diagram mounts. StrictMode effect replay reuses startup, and final unmount disposes even an instance that is still initializing.
28
+
29
+ `TextGraph` can run without a provider when the SDK's default package-relative URLs are served intact. Each standalone component owns its runtime. Bundled applications should use a provider with explicit asset resolution.
30
+
31
+ Use your deployed base path instead of `/` for subdirectory hosting. The [React/Vite sample](https://github.com/drawmotive/textgraph/tree/main/samples/react-vite) demonstrates Vite's `BASE_URL`. No external CDN is needed. Assets follow the [SDK's MIME, CSP and offline requirements](api-v1.md#assets-csp-and-offline-operation); PNG data URLs need `img-src 'self' data:`.
32
+
33
+ ## Component behavior
34
+
35
+ | Prop | Behavior |
36
+ | --- | --- |
37
+ | `source` | Required DSL string; changes trigger rendering. |
38
+ | `alt` | Image description; defaults to `TextGraph diagram`. |
39
+ | `renderOptions` | Defaults to `scale: 1`; `padding` and `maxWidth` use SDK defaults. Set `scale: 2` explicitly for higher raster density. |
40
+ | `loading` | React content shown with `role="status"`; defaults to `Rendering diagram…`. |
41
+ | Other image attributes | Passed to the successful `<img>`, including `className`, `style`, `width`, and `height`. |
42
+
43
+ The component owns `src`, encoding, and cancellation. While new input renders, old images are replaced by loading content. A stale result cannot replace newer input. DSL diagnostics and operational failures appear as escaped text with `role="alert"`; corrected input renders again. Changing only `alt` or image styles does not rerun layout.
44
+
45
+ Images use the render result's logical `displayWidth` and `displayHeight`, so increasing `scale` adds pixels without enlarging the diagram. `maxWidth` limits raster pixels rather than CSS width. Styles default to `maxWidth: '100%'` and `height: 'auto'`; supplied styles merge over these defaults, and explicit image dimensions override the logical dimensions.
46
+
47
+ Older runtimes omit display dimensions. The component then divides raster dimensions by the requested scale; this preserves logical size unless `maxWidth` has lowered the effective density. Deploy matching updated runtime assets for accurate sizing in that case. PNG DPI metadata does not control CSS size.
48
+
49
+ An ordinary React render uses the browser main thread. Native layout already running cannot be preempted by cancellation; for heavy interactive workloads use the [Worker sample](https://github.com/drawmotive/textgraph/tree/main/samples/worker) to move SDK execution off the UI thread. The React component does not automatically create a Worker.
50
+
51
+ ## Server rendering
52
+
53
+ The entry carries `'use client'`. Server rendering emits the same loading placeholder without starting WASM; the browser renders the diagram after hydration. In frameworks such as Next.js, place the provider and resolver function in your own client component, because functions cannot be passed across a server/client serialization boundary.
54
+
55
+ To deliver a finished image in the initial HTML, call `@drawmotive/textgraph/node` during server/build work, persist the PNG, and render a normal `<img>` with its URL. That workflow does not load WASM in the reader's browser.
package/docs/releases.md CHANGED
@@ -7,11 +7,14 @@ Releases are selected deliberately and published by `.github/workflows/release.y
7
7
  | Version | npm dist-tag | Installation |
8
8
  | --- | --- | --- |
9
9
  | `0.1.0-alpha.1` | `alpha` | `npm install @drawmotive/textgraph@alpha` |
10
- | `0.1.0` | `latest` | `npm install @drawmotive/textgraph` |
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 |
11
12
 
12
- An exact prerelease version also works: `npm install @drawmotive/textgraph@0.1.0-alpha.1`. Alpha releases never change `latest`. Until a real stable version exists, default installation has no matching stable version and fails; no placeholder stable version is published. Versions are immutable. To graduate an alpha, prepare and publish a new stable version instead of moving `latest` to an alpha.
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`.
13
14
 
14
- The scripts accept stable SemVer and `X.Y.Z-alpha.N`. Other channels require an explicit release-policy change. The Chinese font package has its own release lifecycle and is not published by this workflow.
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.
15
18
 
16
19
  ## Account setup
17
20
 
@@ -20,6 +23,12 @@ The scripts accept stable SemVer and `X.Y.Z-alpha.N`. Other channels require an
20
23
  3. Once the npm package exists, open its Settings and add a GitHub Actions trusted publisher: owner `drawmotive`, repository `textgraph`, workflow filename `release.yml`, environment `npm`.
21
24
  4. The workflow uses a GitHub-hosted runner, Node.js 22, npm 11.11.1, and `id-token: write`. No long-lived npm token is needed for subsequent releases.
22
25
 
26
+ The trusted publisher for `drawmotive/textgraph`, `release.yml`, and environment `npm` is configured. To configure the equivalent account setting from a terminal, use npm 11.15.0+ (the older CLI omits permissions required by the current API):
27
+
28
+ ```bash
29
+ npm trust github @drawmotive/textgraph --repo drawmotive/textgraph --file release.yml --env npm --allow-publish --yes
30
+ ```
31
+
23
32
  Trusted publishing requires npm 11.5.1+ and Node.js 22.14.0+. Publication from a public repository automatically includes provenance. A private repository does not produce public npm provenance; repository visibility is a separate owner decision. See [npm trusted publishers](https://docs.npmjs.com/trusted-publishers/).
24
33
 
25
34
  ## Prepare a version
@@ -27,15 +36,15 @@ Trusted publishing requires npm 11.5.1+ and Node.js 22.14.0+. Publication from a
27
36
  Native builds belong to the private DrawMotive repository. Commit native source, resource, and bridge changes first, then run there:
28
37
 
29
38
  ```bash
30
- npm run release:textgraph -- 0.1.0-alpha.1
39
+ npm run release:textgraph -- 0.2.1
31
40
  ```
32
41
 
33
- 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.1.0-alpha.1` alias runs the same command.
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.
34
43
 
35
44
  For a JavaScript-only release reusing already verified native bytes, run in this package:
36
45
 
37
46
  ```bash
38
- npm run release:prepare -- 0.1.0-alpha.2
47
+ npm run release:prepare -- VERSION_MATCHING_RELEASE_TARGET
39
48
  npm run release:verify
40
49
  ```
41
50
 
@@ -59,7 +68,7 @@ Commit the package changes on the task branch, review them, and integrate accord
59
68
 
60
69
  ## First publication
61
70
 
62
- When the package does not exist yet, its trusted publisher may not be configurable. Bootstrap the verified release once from an authenticated terminal:
71
+ When the package does not exist yet, its trusted publisher may not be configurable. Bootstrap the verified release once from an authenticated terminal; an initial alpha can also become the npm default:
63
72
 
64
73
  ```bash
65
74
  npm login --registry=https://registry.npmjs.org/
@@ -74,27 +83,26 @@ If npm requires a one-time code, run with `NPM_CONFIG_OTP` set in the local term
74
83
  After preparation, tests, and review, create the tag on the verified package commit:
75
84
 
76
85
  ```bash
77
- git tag -a textgraph-v0.1.0-alpha.2 -m "Release 0.1.0-alpha.2"
78
- git push origin main
79
- git push origin textgraph-v0.1.0-alpha.2
86
+ git tag -a textgraph-v0.2.1 -m "Release 0.2.1"
87
+ git push origin textgraph-v0.2.1
80
88
  ```
81
89
 
82
- The release workflow resolves the tag to a commit, runs the existing three-platform Node.js and three-browser tests, packs the tested checkout, and passes the artifact to the `npm` environment for publication. Stable releases use the same procedure with a version such as `0.1.0`; the script selects `latest` automatically. Never pass a custom dist-tag to bypass the release policy.
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.
83
91
 
84
92
  ## Verify publication and recover
85
93
 
86
94
  ```bash
87
95
  npm view @drawmotive/textgraph dist-tags --json
88
- npm view @drawmotive/textgraph@0.1.0-alpha.1 dist.integrity
89
- npm install @drawmotive/textgraph@0.1.0-alpha.1
96
+ npm view @drawmotive/textgraph@0.2.1 dist.integrity
97
+ npm install @drawmotive/textgraph@0.2.1
90
98
  ```
91
99
 
92
100
  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:
93
101
 
94
102
  ```bash
95
- gh workflow run release.yml --ref textgraph-v0.1.0-alpha.1 -f tag=textgraph-v0.1.0-alpha.1
103
+ gh workflow run release.yml --ref textgraph-v0.2.1 -f tag=textgraph-v0.2.1
96
104
  ```
97
105
 
98
106
  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.
99
107
 
100
- If an alpha accidentally acquires `latest` outside this workflow, restore the previously verified stable version using `npm dist-tag add @drawmotive/textgraph@<STABLE_VERSION> latest`. If no stable version exists, remove only the accidental tag using `npm dist-tag rm @drawmotive/textgraph latest`. Confirm registry state before retrying. Do not unpublish or overwrite versions as a routine recovery step.
108
+ 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.
@@ -4,7 +4,7 @@
4
4
  "includedFrameworks": [
5
5
  {
6
6
  "name": "Microsoft.NETCore.App",
7
- "version": "10.0.8"
7
+ "version": "10.0.12"
8
8
  }
9
9
  ],
10
10
  "wasmHostProperties": {
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file