domotion-svg 0.14.0 → 0.16.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 (123) hide show
  1. package/README.md +68 -9
  2. package/dist/animation/animator.d.ts +9 -0
  3. package/dist/animation/animator.js +287 -145
  4. package/dist/animation/composite.d.ts +133 -0
  5. package/dist/animation/composite.js +243 -0
  6. package/dist/animation/embed-namespace.d.ts +52 -0
  7. package/dist/animation/embed-namespace.js +89 -0
  8. package/dist/animation/embed-timeline.d.ts +76 -0
  9. package/dist/animation/embed-timeline.js +212 -0
  10. package/dist/animation/index.d.ts +3 -0
  11. package/dist/animation/index.js +7 -0
  12. package/dist/animation/overlay-schema.d.ts +2 -0
  13. package/dist/animation/overlay-schema.js +13 -2
  14. package/dist/animation/resolve-overlays.d.ts +3 -3
  15. package/dist/animation/resolve-overlays.js +2 -2
  16. package/dist/animation/svg-meta.d.ts +31 -0
  17. package/dist/animation/svg-meta.js +49 -0
  18. package/dist/capture/clip-rect.d.ts +29 -0
  19. package/dist/capture/clip-rect.js +23 -0
  20. package/dist/capture/embed.d.ts +13 -0
  21. package/dist/capture/embed.js +16 -0
  22. package/dist/capture/emoji.d.ts +0 -9
  23. package/dist/capture/emoji.js +73 -75
  24. package/dist/capture/index.d.ts +5 -19
  25. package/dist/capture/index.js +111 -104
  26. package/dist/capture/initial-letter-probe.js +2 -8
  27. package/dist/capture/script/index.js +1 -1
  28. package/dist/capture/script.generated.js +1 -1
  29. package/dist/capture/types.d.ts +528 -520
  30. package/dist/cli/animate.d.ts +197 -16
  31. package/dist/cli/animate.js +506 -203
  32. package/dist/cli/capture.js +2 -1
  33. package/dist/cli/common.d.ts +20 -1
  34. package/dist/cli/common.js +53 -1
  35. package/dist/cli/composite-config-json-schema.d.ts +33 -0
  36. package/dist/cli/composite-config-json-schema.js +67 -0
  37. package/dist/cli/composite.d.ts +83 -0
  38. package/dist/cli/composite.js +222 -0
  39. package/dist/cli/index.js +27 -0
  40. package/dist/cli/review.js +4 -4
  41. package/dist/cli/scrubber.d.ts +3 -3
  42. package/dist/cli/scrubber.js +12 -12
  43. package/dist/cli/svg-to-image-core.d.ts +60 -0
  44. package/dist/cli/svg-to-image-core.js +159 -0
  45. package/dist/cli/svg-to-image.d.ts +14 -0
  46. package/dist/cli/svg-to-image.js +143 -0
  47. package/dist/cli/svg-to-video-core.d.ts +2 -8
  48. package/dist/cli/svg-to-video-core.js +9 -29
  49. package/dist/cli/template.d.ts +15 -0
  50. package/dist/cli/template.js +136 -0
  51. package/dist/cli/term.js +21 -4
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.js +7 -0
  54. package/dist/render/borders.js +35 -51
  55. package/dist/render/clip-path.d.ts +9 -0
  56. package/dist/render/clip-path.js +173 -0
  57. package/dist/render/conic-raster.js +11 -19
  58. package/dist/render/element-tree-to-svg.d.ts +3 -99
  59. package/dist/render/element-tree-to-svg.js +3444 -5522
  60. package/dist/render/embedded-font-builder.js +1 -0
  61. package/dist/render/font-resolution.d.ts +508 -0
  62. package/dist/render/font-resolution.js +3099 -0
  63. package/dist/render/form-controls.js +1 -1
  64. package/dist/render/glyph-helper.js +6 -0
  65. package/dist/render/gradient-defs.d.ts +37 -0
  66. package/dist/render/gradient-defs.js +571 -0
  67. package/dist/render/gradients.js +1 -18
  68. package/dist/render/helper-acquire.js +4 -1
  69. package/dist/render/image-pattern.d.ts +24 -0
  70. package/dist/render/image-pattern.js +256 -0
  71. package/dist/render/mask.d.ts +69 -0
  72. package/dist/render/mask.js +941 -0
  73. package/dist/render/stacking.d.ts +99 -0
  74. package/dist/render/stacking.js +411 -0
  75. package/dist/render/text-to-path.d.ts +9 -354
  76. package/dist/render/text-to-path.js +41 -3414
  77. package/dist/render/text.js +17 -30
  78. package/dist/render/transforms.js +6 -3
  79. package/dist/render/unicode-classification.d.ts +51 -0
  80. package/dist/render/unicode-classification.js +376 -0
  81. package/dist/scroll/composer.js +222 -212
  82. package/dist/scrubber/client.js +1 -1
  83. package/dist/scrubber/server.d.ts +1 -1
  84. package/dist/scrubber/server.js +8 -6
  85. package/dist/templates/builtin/background-loop.d.ts +170 -0
  86. package/dist/templates/builtin/background-loop.js +493 -0
  87. package/dist/templates/builtin/chart.d.ts +141 -0
  88. package/dist/templates/builtin/chart.js +436 -0
  89. package/dist/templates/builtin/chat.d.ts +65 -0
  90. package/dist/templates/builtin/chat.js +189 -0
  91. package/dist/templates/builtin/device-mockup.d.ts +39 -0
  92. package/dist/templates/builtin/device-mockup.js +82 -0
  93. package/dist/templates/builtin/kinetic-text.d.ts +109 -0
  94. package/dist/templates/builtin/kinetic-text.js +325 -0
  95. package/dist/templates/builtin/lower-third.d.ts +45 -0
  96. package/dist/templates/builtin/lower-third.js +118 -0
  97. package/dist/templates/builtin/subscribe.d.ts +44 -0
  98. package/dist/templates/builtin/subscribe.js +162 -0
  99. package/dist/templates/index.d.ts +19 -0
  100. package/dist/templates/index.js +19 -0
  101. package/dist/templates/json-schema.d.ts +29 -0
  102. package/dist/templates/json-schema.js +70 -0
  103. package/dist/templates/registry.d.ts +24 -0
  104. package/dist/templates/registry.js +62 -0
  105. package/dist/templates/render.d.ts +24 -0
  106. package/dist/templates/render.js +87 -0
  107. package/dist/templates/run-single-frame.d.ts +18 -0
  108. package/dist/templates/run-single-frame.js +27 -0
  109. package/dist/templates/types.d.ts +111 -0
  110. package/dist/templates/types.js +30 -0
  111. package/dist/terminal/cast.js +1 -1
  112. package/dist/terminal/incremental.js +19 -21
  113. package/dist/terminal/index.js +7 -19
  114. package/dist/terminal/pty.d.ts +7 -15
  115. package/dist/terminal/pty.js +56 -0
  116. package/dist/terminal/render.d.ts +17 -0
  117. package/dist/terminal/render.js +25 -0
  118. package/dist/terminal/theme.d.ts +14 -0
  119. package/dist/terminal/theme.js +22 -0
  120. package/llms.txt +254 -0
  121. package/package.json +11 -8
  122. package/schemas/animate-config.schema.json +24 -4
  123. package/schemas/composite-config.schema.json +200 -0
package/README.md CHANGED
@@ -2,7 +2,25 @@
2
2
  <img src="examples/output/domotion-word-demo.svg" alt="Domotion — an animated wordmark cycling through twenty neon-retro typographic variants of the word domotion" width="600">
3
3
  </p>
4
4
 
5
- DOM-to-animated-SVG renderer. Captures HTML/CSS rendered in headless Chromium and converts the captured tree into a self-contained SVG with optional CSS animations — pixel-faithful to what Chromium painted, scales crisply at any size, and embeds without external assets.
5
+ <p align="center">
6
+ <strong><a href="https://brianwestphal.github.io/domotion/">🌐 Website &amp; docs</a></strong>
7
+ &nbsp;·&nbsp;
8
+ <a href="https://brianwestphal.github.io/domotion/showcase/">Showcase</a>
9
+ &nbsp;·&nbsp;
10
+ <a href="https://brianwestphal.github.io/domotion/start/quickstart/">Quick start</a>
11
+ &nbsp;·&nbsp;
12
+ <a href="https://github.com/brianwestphal/domotion">GitHub</a>
13
+ </p>
14
+
15
+ **Domotion turns real HTML/CSS into one self-contained, animated SVG** — an accurate reproduction of the rendered page, with optional animation and simulated interaction built in. Text is emitted as real glyph paths, so it looks identical across browsers; the output scales crisply at any size and embeds anywhere with a plain `<img>`, no external assets.
16
+
17
+ Beyond raw capture it ships a **template library** that turns a few flags into a polished animated SVG, **terminal-session capture** (a recording → an animated terminal), multi-frame **animation** with transitions, overlays, and simulated interaction, **device-chrome** framing, **nested compositing** (animated layers inside animated layers), one-command **SVG → MP4/WebM**, and a fidelity **review** tool.
18
+
19
+ <p align="center">
20
+ <img src="examples/output/hero-product-demo.svg" alt="An analytics dashboard assembling itself inside a browser window — KPI cards rise in, a bar chart grows with its peak highlighted, a search query types itself, and a nav item is clicked — all in one self-contained animated SVG" width="760">
21
+ </p>
22
+
23
+ <p align="center"><sub>A real UI captured and brought to life — one self-contained SVG. <a href="https://brianwestphal.github.io/domotion/showcase/">More demos →</a></sub></p>
6
24
 
7
25
  ## Why
8
26
 
@@ -16,15 +34,13 @@ Domotion captures real HTML/CSS as it renders in Chromium, then emits a single i
16
34
 
17
35
  ## Status
18
36
 
19
- Earlyextracted in 2026-04 from the slicekit project where it had been incubating as `tools/svg-demo-gen`. APIs may still shift while the project's external surface stabilizes.
37
+ Actively developed, with a broad shipped surface capture, multi-frame animation (transitions, overlays, simulated interaction), the template library, terminal capture, nested compositing, and the video/image exports — exercised by an extensive visual-regression suite. The CLIs and the animate-config schema are stable in practice.
20
38
 
21
39
  ## Platform support
22
40
 
23
- Domotion ships as a normal npm package and is **designed** to work on macOS, Linux, and Windows the captured SVG is meant to be pixel-faithful to Chromium on whichever platform the capture is running on (CoreText fallback on macOS, fontconfig on Linux, DirectWrite on Windows).
41
+ Domotion runs on **macOS, Linux, and Windows**, and all three are calibrated. It renders text by extracting real system-font glyph outlines and matching how the browser falls back between fonts on the platform you run it on (CoreText on macOS, fontconfig on Linux, DirectWrite on Windows). macOS is held to pixel-exact parity; Linux and Windows match the browser's glyph selection and metrics within a small native-hinting margin (the residual is unhinted-outline-vs-native-raster rasterization, not missing calibration), and both are gated by visual-regression CI.
24
42
 
25
- **Today it's only actively tested and calibrated on macOS.** Linux and Windows are roadmap items: cross-platform system-font path discovery, per-platform fallback-font chains calibrated against the host Chromium, optional bundled fallback fonts when no local match resolves, and CI coverage on both platforms. The package will install and run on Linux/Windows, but text rendering won't yet match the host Chromium as faithfully as it does on macOS.
26
-
27
- If you'd like to help with cross-platform support — testing on Linux or Windows, reporting issues you hit, or sending fixes — please open an issue or PR on [GitHub](https://github.com/brianwestphal/domotion). Bug reports against macOS are also welcome.
43
+ Issues, fixes, and platform feedback are welcome on [GitHub](https://github.com/brianwestphal/domotion).
28
44
 
29
45
  ## Install
30
46
 
@@ -41,8 +57,10 @@ yourself to keep the first job's runtime down.
41
57
  The fastest way in is the `domotion` CLI — no TypeScript, no Playwright bring-up. Point it at a URL or HTML file:
42
58
 
43
59
  ```bash
44
- # Zero-install: run the published CLI straight from npm.
45
- npx domotion-svg capture https://example.com -o example.svg
60
+ # Zero-install: run the published CLI straight from npm. The package name is
61
+ # domotion-svg; -p installs it and `domotion` selects the bin (the package ships
62
+ # several bins, so the bin must be named explicitly).
63
+ npx -p domotion-svg domotion capture https://example.com -o example.svg
46
64
 
47
65
  # Capture a URL as SVG.
48
66
  domotion capture https://example.com -o example.svg
@@ -66,6 +84,31 @@ domotion animate ./demo.json
66
84
 
67
85
  The config describes each frame (input, duration, transition) plus a declarative surface for interaction demos: continuous-session frames that carry client-side state across steps (omit `input` / set `"continue": true`), DOM-mutation and interaction actions, richer readiness waits (`waitForText` / `waitForGone` / `waitForCount`), typing / tap / svg / blink overlays that can anchor to an element's box, an on-screen `cursor` (explicit or `"auto"`), `vars` + `${}` interpolation, and a small `evaluate` escape hatch. See `domotion --help` for the full grammar and the [Quick start](https://brianwestphal.github.io/domotion/start/quickstart/) for a walkthrough.
68
86
 
87
+ ### Templates — animated SVGs from a few flags
88
+
89
+ The fastest way to a polished result without writing any HTML. Each built-in is a parameterized generator; pass a few flags and get a self-contained animated SVG. `domotion template list` shows them, `domotion template <name> --help` shows a template's parameters.
90
+
91
+ ```bash
92
+ domotion template lower-third --title "Ada Lovelace" --subtitle "First Programmer" -o banner.svg
93
+ domotion template chart --type donut --data "42,28,18,12" --labels "Search,Direct,Social,Email" -o chart.svg
94
+ domotion template kinetic-text --text "Ship it" --variant pop --by char -o title.svg
95
+ ```
96
+
97
+ Built-ins: **lower-third** (broadcast banner) · **kinetic-text** (animated typography) · **chart** (column / bar / line / pie / donut) · **chat** (message thread) · **subscribe** (follow pop-up) · **background-loop** (seamless looping background) · **device-mockup** (wrap a page in a phone / browser / window bezel). Third-party templates are npm packages named `domotion-template-<name>`.
98
+
99
+ ### Terminal sessions
100
+
101
+ Turn a recorded terminal session into a self-contained animated SVG — real text, real color, native SVG (no raster frames). Record with [asciinema](https://asciinema.org), then convert:
102
+
103
+ ```bash
104
+ asciinema rec demo.cast -c "npm test"
105
+ domotion term --cast demo.cast -o demo.svg
106
+ ```
107
+
108
+ ### Compositing — animated layers inside animated layers
109
+
110
+ `domotion composite` stacks layers — a `cast`, a `template`, or a pre-rendered `svg`, any of which may be animated — into one SVG, each placed and on its own timeline with its animation preserved. This is how you nest one animated thing inside another, e.g. a terminal window resizing on a desktop. See `domotion composite --help` and `examples/composite/`.
111
+
69
112
  ### Export to video
70
113
 
71
114
  The package also ships a standalone `svg-to-video` CLI that renders an animated SVG (a `domotion animate` output, or any CSS-/SMIL-animated SVG) to a video file. It steps the animation timeline frame by frame in Chromium for frame-accurate timing, then pipes the frames to **ffmpeg** (a required external dependency — install via `brew` / `apt` / `winget`).
@@ -80,6 +123,19 @@ svg-to-video demo.svg -o demo.webm --format vp9 --fps 60 --music bed.mp3
80
123
 
81
124
  Supports target size (`--width`/`--height`, aspect-preserving), `--fps`, `--format` / `--container`, supersampling (`--scale`), background music / foreground audio / captions, and a disk-space pre-flight. See `svg-to-video --help`.
82
125
 
126
+ ### Export to a still image
127
+
128
+ To turn a single SVG into an image — to look at a render, embed a thumbnail, or hand off a flat asset — the package ships an `svg-to-image` CLI. The output format follows the `-o` extension: PNG / WebP / AVIF / TIFF (keep alpha for transparent SVGs), JPEG (`--quality`), or a single-page vector PDF. (WebP/AVIF/TIFF are transcoded with the bundled `sharp` — no extra install.)
129
+
130
+ ```bash
131
+ svg-to-image card.svg -o card.png # PNG at the SVG's intrinsic size
132
+ svg-to-image card.svg -o card@2x.png --scale 2 # crisp retina (2×) raster
133
+ svg-to-image demo.svg -o frame.png --at 4000 # one frame of an animated SVG, at 4s
134
+ svg-to-image poster.svg -o poster.pdf # vector PDF
135
+ ```
136
+
137
+ `--at <ms>` samples an animated SVG's timeline, `--width`/`--height` contain preserving aspect, `--scale` supersamples raster output. See `svg-to-image --help`.
138
+
83
139
  ### Reviewing a regression
84
140
 
85
141
  If a capture comes out looking different from how Chromium painted the source page, the package ships an `svg-review` CLI to help you file a focused bug report. Capture once with `--debug` to get a reproduction bundle (HAR + the Chromium screenshot of the source + the SVG we produced), then open the bundle in the local review UI:
@@ -91,6 +147,8 @@ svg-review --expected example.debug/expected.png --actual example.debug/actual.s
91
147
 
92
148
  The browser opens a single review card showing the expected / actual / diff PNGs. Arrow keys cycle through the three at full size; drag on any image to mark a problem region and caption it. The side panel builds a GitHub-issue-ready Markdown block as you go — copy it, then file the issue at <https://github.com/brianwestphal/domotion/issues/new> and attach `expected.png` + `actual.svg` so a maintainer can reproduce.
93
149
 
150
+ For an *animated* SVG, the package also ships `svg-scrubber` — a local video-style bench to play / pause / scrub / mark an in-out range, export the current frame as PNG, export the range as MP4, or trim it to a new self-contained animated SVG.
151
+
94
152
  ### Scripting API
95
153
 
96
154
  When you outgrow the CLI — custom interaction loops, programmatic frame composition, custom overlays — the same primitives are available as a library:
@@ -126,7 +184,8 @@ npm run demos:examples # run the bundled example demo scripts
126
184
 
127
185
  - `FEATURES.md` — per-feature support checklist with links to test fixtures.
128
186
  - `docs/` — requirements docs covering rendering fidelity, supported CSS features, and known caveats.
129
- - `CLAUDE.md` — guidance for AI assistants working in this repo.
187
+ - [`llms.txt`](llms.txt)a concise, self-contained guide for **AI agents using Domotion as a tool** (Claude, Cursor, etc.): the CLIs, the config schema, the template library, the API, and the gotchas. Point your agent at it.
188
+ - `CLAUDE.md` — guidance for AI assistants working *on this repo's* source (different audience from `llms.txt`).
130
189
 
131
190
  ## License
132
191
 
@@ -24,6 +24,15 @@ export interface AnimationFrame {
24
24
  cullCss?: string;
25
25
  /** Duration this frame is shown (ms) */
26
26
  duration: number;
27
+ /**
28
+ * DM-1319: this frame's `svgContent` is itself a self-contained *animated* SVG
29
+ * (a `cast` / `template` frame) whose internal timeline should start when the
30
+ * frame becomes visible, not at the master-loop origin. Set to the embedded
31
+ * content's own play length (ms); the animator re-anchors its keyframes into
32
+ * the `[frameStart, frameStart + period]` window of the master loop (see
33
+ * `offsetEmbeddedAnimatedSvgTimeline`). Omit for ordinary captured frames.
34
+ */
35
+ embeddedAnimationPeriodMs?: number;
27
36
  /** Transition to next frame */
28
37
  transition?: {
29
38
  /**