sketchmark 2.1.9 → 2.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.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: sketchmark
3
+ description: Entry point for Sketchmark kernel, design, animation, and render/edit/preview guidance. Use when working with Sketchmark `.visual.json`, generators, validation, rendering, timelines, or previews.
4
+ ---
5
+
6
+ # Sketchmark
7
+
8
+ Use the smallest file needed:
9
+
10
+ - `kernel.md`: valid document shape, element properties, paints, effects, timelines, curves, and animatable tracks.
11
+ - `design.md`: broad composition and static visual construction guidance.
12
+ - `animation.md`: broad timeline and motion guidance.
13
+ - `render.md`: validate, render, edit, preview, export, and debug workflow.
14
+
15
+ Keep `.visual.json` output pure kernel: `version`, `canvas`, and `elements`.
16
+ When working inside this repository, prefer example generator scripts such as `examples/make-*.cjs` over hand-authoring only generated `.visual.json` files.
@@ -0,0 +1,67 @@
1
+ # Animation
2
+
3
+ Use this for timeline creation, motion timing, reveals, transitions, and animated visual states.
4
+
5
+ ## Boundary
6
+
7
+ - Animation is stored in element-local `timeline.tracks`.
8
+ - Track names must be valid animatable properties from `kernel.md`.
9
+ - Curves are timeline curve objects.
10
+ - Helper functions may exist in generator code, but their output is only kernel timelines.
11
+
12
+ ## Process
13
+
14
+ 1. Create a readable static frame first.
15
+ 2. Choose which element or group owns each motion.
16
+ 3. Animate parent groups for broad movement.
17
+ 4. Animate child elements for local changes.
18
+ 5. Add keyframes at clear beats.
19
+ 6. Use explicit curves when timing matters.
20
+ 7. Validate.
21
+ 8. Render checkpoint frames at key times.
22
+
23
+ ## Track Selection
24
+
25
+ - Position: `position`, `x`, `y`.
26
+ - Visibility: `opacity`.
27
+ - Transform: `rotation`, `scale`, `scaleX`, `scaleY`, `origin`.
28
+ - Path drawing: `drawStart`, `drawEnd`.
29
+ - Text changes: `text`, `lines`.
30
+ - Paint changes: `fill`, `stroke`, paint subproperties.
31
+ - Reveal: `clip.d`, `mask.d`, `mask.opacity`.
32
+ - Effects: `effects.*`.
33
+
34
+ ## Keyframes
35
+
36
+ Preferred object form:
37
+
38
+ ```js
39
+ { time: 0, value: [0, 0], out: { type: "cubicBezier", x1: 0.16, y1: 1, x2: 0.3, y2: 1 } }
40
+ ```
41
+
42
+ Tuple form:
43
+
44
+ ```js
45
+ [0, [0, 0]]
46
+ ```
47
+
48
+ ## Curves
49
+
50
+ - `cubicBezier`: smooth timing.
51
+ - `graph`: custom normalized timing.
52
+ - `hold`: discrete switch.
53
+
54
+ ## Timing
55
+
56
+ - Use seconds.
57
+ - Keep keyframes sorted by time.
58
+ - Use short names for curve constants in generator code.
59
+ - Use `hold` for instant changes.
60
+ - Use multiple sampled keyframes for path or radius style changes because path data is discrete.
61
+
62
+ ## Final Check
63
+
64
+ - Every animated track exists in `kernel.md`.
65
+ - Keyframes are sorted.
66
+ - Curve fields contain curve objects.
67
+ - The animation still reads at checkpoint frames.
@@ -0,0 +1,59 @@
1
+ # Design
2
+
3
+ Use this for composition, layout, typography, visual hierarchy, and static visual construction.
4
+
5
+ ## Boundary
6
+
7
+ - Output kernel elements only: `path`, `text`, `image`, `point`, `group`.
8
+ - Higher-level objects compile to kernel elements.
9
+ - Keep authoring helper names out of `.visual.json`.
10
+
11
+ ## Process
12
+
13
+ 1. Set `canvas.width`, `canvas.height`, optional `background`, `duration`, and `fps`.
14
+ 2. Define reusable constants in generator code: colors, font family, spacing, stroke widths.
15
+ 3. Build from back to front: background, large groups, content, details.
16
+ 4. Use `group` for local coordinate systems.
17
+ 5. Use `path` for shape geometry.
18
+ 6. Use `text` for all labels and copy.
19
+ 7. Use `image` only with explicit size and fit.
20
+ 8. Validate the document.
21
+ 9. Render at least one preview frame.
22
+
23
+ ## Layout
24
+
25
+ - Use explicit `x` and `y`.
26
+ - Use groups to move related elements together.
27
+ - Use consistent margins and spacing.
28
+ - Keep important content inside the canvas.
29
+ - Prefer stable dimensions over inferred layout.
30
+
31
+ ## Text
32
+
33
+ - Set `align` and `valign`.
34
+ - Set `fontSize`, `lineHeight`, `weight`, and `fill`.
35
+ - Use `text` with newlines or `lines` for multiline text.
36
+ - Use `maxWidth` and `wrap` only when supported by the renderer path being used.
37
+
38
+ ## Shapes
39
+
40
+ - Rectangle: `path`.
41
+ - Rounded rectangle: `path`.
42
+ - Circle/ellipse: `path`.
43
+ - Arrow: `path`.
44
+ - Divider: `path` with `stroke`.
45
+ - Clip/reveal shape: `clip.d` or `mask.d`.
46
+
47
+ ## Images
48
+
49
+ - Set `src`, `x`, `y`, `width`, `height`.
50
+ - Use `fit`.
51
+ - Use `source.*` for cropping.
52
+ - Use `clip.d` for rounded or custom image boundaries.
53
+
54
+ ## Final Check
55
+
56
+ - No non-kernel element types.
57
+ - No metadata or editor state.
58
+ - All visual objects have explicit position and size.
59
+ - Text is readable in the target canvas.
@@ -0,0 +1,354 @@
1
+ # Kernel
2
+
3
+ ## Package Entry Points
4
+
5
+ - `sketchmark`
6
+ - `sketchmark/presets`
7
+ - `sketchmark/browser-export`
8
+ - `sketchmark/render`
9
+ - `sketchmark/edit`
10
+ - `sketchmark/editor`
11
+ - `sketchmark/preview`
12
+ - `sketchmark/schema`
13
+ - CLI: `sketchmark`
14
+
15
+ ## Root Kernel Exports
16
+
17
+ - types
18
+ - validate
19
+ - normalize
20
+ - diagnostics
21
+ - schema
22
+ - keyframes
23
+ - edit namespace and direct edit helpers
24
+ - animatable
25
+ - render namespace and direct render helpers
26
+
27
+ Preferred package API:
28
+
29
+ ```js
30
+ const { render, edit, validateVisualDocument } = require("sketchmark");
31
+
32
+ const svg = render.svg(doc, { time: 1 });
33
+ const html = render.html(doc);
34
+ const embed = render.embedHtml(doc, { title: "Preview" });
35
+ const nextDoc = edit.setProperty(doc, "element-id", "fill", "#22c55e");
36
+ ```
37
+
38
+ UI entry points stay separate:
39
+
40
+ ```js
41
+ const { editorHtml } = require("sketchmark/editor");
42
+ const { previewHtml } = require("sketchmark/preview");
43
+ ```
44
+
45
+ ## Document
46
+
47
+ - `version`: `1`
48
+ - `canvas`: `VisualCanvas`
49
+ - `elements`: `VisualElement[]`
50
+
51
+ ## Canvas
52
+
53
+ - `width`: number
54
+ - `height`: number
55
+ - `background`: string
56
+ - `duration`: number
57
+ - `fps`: number
58
+
59
+ ## Element Types
60
+
61
+ - `path`
62
+ - `text`
63
+ - `image`
64
+ - `point`
65
+ - `group`
66
+
67
+ ## Common Element Properties
68
+
69
+ - `id`: string
70
+ - `type`: element type
71
+ - `opacity`: number
72
+ - `fill`: paint
73
+ - `stroke`: paint
74
+ - `strokeWidth`: number
75
+ - `strokeCap`: `butt | round | square`
76
+ - `strokeJoin`: `miter | round | bevel`
77
+ - `miterLimit`: number
78
+ - `dashArray`: number[]
79
+ - `dashOffset`: number
80
+ - `drawStart`: number
81
+ - `drawEnd`: number
82
+ - `effects`: effects
83
+ - `blendMode`: string
84
+ - `rotation`: number
85
+ - `scale`: number
86
+ - `scaleX`: number
87
+ - `scaleY`: number
88
+ - `origin`: `[number, number]`
89
+ - `clip`: clip shape
90
+ - `mask`: mask shape
91
+ - `timeline`: element timeline
92
+
93
+ ## Path Element
94
+
95
+ - `type`: `"path"`
96
+ - `d`: SVG path data string
97
+ - `x`: number
98
+ - `y`: number
99
+ - common properties
100
+
101
+ ## Text Element
102
+
103
+ - `type`: `"text"`
104
+ - `x`: number
105
+ - `y`: number
106
+ - `text`: string
107
+ - `lines`: string[]
108
+ - `align`: `left | center | right`
109
+ - `valign`: `top | middle | bottom`
110
+ - `fontSize`: number
111
+ - `fontFamily`: string
112
+ - `weight`: number | string
113
+ - `fontStyle`: string
114
+ - `lineHeight`: number
115
+ - `letterSpacing`: number
116
+ - `maxWidth`: number
117
+ - `wrap`: boolean
118
+ - common properties
119
+
120
+ ## Image Element
121
+
122
+ - `type`: `"image"`
123
+ - `src`: string
124
+ - `x`: number
125
+ - `y`: number
126
+ - `width`: number
127
+ - `height`: number
128
+ - `fit`: `fill | contain | cover`
129
+ - `source.x`: number
130
+ - `source.y`: number
131
+ - `source.width`: number
132
+ - `source.height`: number
133
+ - `source.imageWidth`: number
134
+ - `source.imageHeight`: number
135
+ - common properties
136
+
137
+ ## Point Element
138
+
139
+ - `type`: `"point"`
140
+ - `x`: number
141
+ - `y`: number
142
+ - common properties
143
+
144
+ ## Group Element
145
+
146
+ - `type`: `"group"`
147
+ - `x`: number
148
+ - `y`: number
149
+ - `width`: number
150
+ - `height`: number
151
+ - `children`: `VisualElement[]`
152
+ - common properties
153
+
154
+ ## Paint
155
+
156
+ - string color
157
+ - linear gradient
158
+ - radial gradient
159
+ - pattern
160
+
161
+ ## Linear Gradient Paint
162
+
163
+ - `type`: `"linearGradient"`
164
+ - `from`: `[number, number]`
165
+ - `to`: `[number, number]`
166
+ - `stops`: gradient stops
167
+
168
+ ## Radial Gradient Paint
169
+
170
+ - `type`: `"radialGradient"`
171
+ - `center`: `[number, number]`
172
+ - `radius`: number
173
+ - `focus`: `[number, number]`
174
+ - `stops`: gradient stops
175
+
176
+ ## Pattern Paint
177
+
178
+ - `type`: `"pattern"`
179
+ - `src`: string
180
+ - `x`: number
181
+ - `y`: number
182
+ - `width`: number
183
+ - `height`: number
184
+ - `fit`: `fill | contain | cover`
185
+ - `opacity`: number
186
+
187
+ ## Gradient Stop
188
+
189
+ - `[offset, color]`
190
+ - `{ offset, color }`
191
+
192
+ ## Clip Shape
193
+
194
+ - `type`: `"path"`
195
+ - `d`: SVG path data string
196
+
197
+ ## Mask Shape
198
+
199
+ - `type`: `"path"`
200
+ - `d`: SVG path data string
201
+ - `opacity`: number
202
+
203
+ ## Effects
204
+
205
+ - `blur`: number
206
+ - `brightness`: number
207
+ - `contrast`: number
208
+ - `saturate`: number
209
+ - `hueRotate`: number
210
+ - `shadow.dx`: number
211
+ - `shadow.dy`: number
212
+ - `shadow.blur`: number
213
+ - `shadow.color`: string
214
+ - `shadow.opacity`: number
215
+
216
+ ## Timeline
217
+
218
+ - `start`: number
219
+ - `end`: number
220
+ - `tracks`: record of animatable property names to timeline tracks
221
+
222
+ ## Timeline Track
223
+
224
+ - `keyframes`: timeline keyframes
225
+ - `curve`: timeline curve
226
+ - `ease`: string
227
+
228
+ ## Keyframe Tuple
229
+
230
+ - `[time, value]`
231
+
232
+ ## Keyframe Object
233
+
234
+ - `time`: number
235
+ - `value`: timeline value
236
+ - `in`: timeline curve
237
+ - `out`: timeline curve
238
+ - `interpolation`: timeline curve
239
+
240
+ ## Timeline Curve
241
+
242
+ - `{ type: "graph", points: [number, number][] }`
243
+ - `{ type: "cubicBezier", x1: number, y1: number, x2: number, y2: number }`
244
+ - `{ type: "hold" }`
245
+
246
+ ## Timeline Values
247
+
248
+ - number
249
+ - string
250
+ - `[number, number]`
251
+ - number[]
252
+ - string[]
253
+ - JSON object
254
+
255
+ ## Animatable Common Tracks
256
+
257
+ - `position`: path, point, text, image, group
258
+ - `x`: path, point, text, image, group
259
+ - `y`: path, point, text, image, group
260
+ - `opacity`: path, point, text, image, group
261
+ - `rotation`: path, text, image, group
262
+ - `scale`: path, text, image, group
263
+ - `scaleX`: path, text, image, group
264
+ - `scaleY`: path, text, image, group
265
+ - `origin`: path, text, image, group
266
+ - `blendMode`: path, text, image, group
267
+ - `clip.d`: path, text, image, group
268
+ - `mask.d`: path, text, image, group
269
+ - `mask.opacity`: path, text, image, group
270
+
271
+ ## Animatable Path Tracks
272
+
273
+ - `d`
274
+ - `fill`
275
+ - `stroke`
276
+ - `strokeWidth`
277
+ - `strokeCap`
278
+ - `strokeJoin`
279
+ - `miterLimit`
280
+ - `dashArray`
281
+ - `dashOffset`
282
+ - `drawStart`
283
+ - `drawEnd`
284
+
285
+ ## Animatable Text Tracks
286
+
287
+ - `text`
288
+ - `lines`
289
+ - `align`
290
+ - `valign`
291
+ - `fontFamily`
292
+ - `fontStyle`
293
+ - `fontSize`
294
+ - `lineHeight`
295
+ - `letterSpacing`
296
+ - `maxWidth`
297
+ - `weight`
298
+ - `fill`
299
+
300
+ ## Animatable Image Tracks
301
+
302
+ - `width`
303
+ - `height`
304
+ - `src`
305
+ - `fit`
306
+ - `source.x`
307
+ - `source.y`
308
+ - `source.width`
309
+ - `source.height`
310
+
311
+ ## Animatable Group Tracks
312
+
313
+ - `width`
314
+ - `height`
315
+
316
+ ## Animatable Effects Tracks
317
+
318
+ - `effects.blur`
319
+ - `effects.brightness`
320
+ - `effects.contrast`
321
+ - `effects.saturate`
322
+ - `effects.hueRotate`
323
+ - `effects.shadow.dx`
324
+ - `effects.shadow.dy`
325
+ - `effects.shadow.blur`
326
+ - `effects.shadow.color`
327
+ - `effects.shadow.opacity`
328
+
329
+ ## Animatable Paint Tracks
330
+
331
+ - `fill.x`
332
+ - `fill.y`
333
+ - `fill.width`
334
+ - `fill.height`
335
+ - `fill.opacity`
336
+ - `fill.from`
337
+ - `fill.to`
338
+ - `fill.center`
339
+ - `fill.focus`
340
+ - `fill.radius`
341
+ - `fill.stops.N.offset`
342
+ - `fill.stops.N.color`
343
+ - `stroke.x`
344
+ - `stroke.y`
345
+ - `stroke.width`
346
+ - `stroke.height`
347
+ - `stroke.opacity`
348
+ - `stroke.from`
349
+ - `stroke.to`
350
+ - `stroke.center`
351
+ - `stroke.focus`
352
+ - `stroke.radius`
353
+ - `stroke.stops.N.offset`
354
+ - `stroke.stops.N.color`
@@ -0,0 +1,166 @@
1
+ # Render, Edit, Preview
2
+
3
+ Use this for validating, rendering, editing, previewing, exporting, and debugging Sketchmark files.
4
+ If the goal is a reusable preview another UI or AI agent can mount directly, prefer a self-contained embed HTML over a one-off SVG frame.
5
+ Package-facing docs may use generic placeholder paths, but inside this repository the default authoring workflow is generator-first: create or update `examples/make-*.cjs` or `.js`, then regenerate the derived `.visual.json` or `.embed.html` artifacts.
6
+ Do not default to hand-writing only a generated `.visual.json` file for a new repo example unless the user explicitly asks for raw JSON only.
7
+
8
+ ## Files
9
+
10
+ - Repo convention for examples: `examples/make-name.cjs` -> `examples/name.visual.json`
11
+ - Repo convention for embed demos: `examples/make-name.cjs` -> `examples/name.embed.html` and optional `examples/name.host.html`
12
+ - Kernel document: `path/to/document.visual.json`
13
+ - Optional generator script: `path/to/generator.cjs`
14
+ - Optional standalone embed output: `path/to/preview.embed.html`
15
+ - Optional host iframe page: `path/to/preview.host.html`
16
+ - Schema: `schema/visual.schema.json`
17
+ - CLI: `bin/sketchmark.cjs`
18
+ - Package API: `sketchmark`, `sketchmark/render`, `sketchmark/edit`
19
+ - UI API: `sketchmark/editor`, `sketchmark/preview`
20
+ - Browser export entrypoint: `sketchmark/browser-export`
21
+
22
+ ## Generate
23
+
24
+ If the project uses a generator script, build first when needed and run that script:
25
+
26
+ ```bash
27
+ npm run build
28
+ node path/to/generator.cjs
29
+ ```
30
+
31
+ Inside this repo, prefer this pattern for new examples:
32
+
33
+ ```bash
34
+ npm run build
35
+ node examples/make-name.cjs
36
+ ```
37
+
38
+ That generator should usually be the source of truth, with `.visual.json`, `.embed.html`, or `.host.html` checked in as generated artifacts when the repo already follows that pattern.
39
+
40
+ ## Validate
41
+
42
+ In code:
43
+
44
+ ```js
45
+ const { validateVisualDocument } = require("sketchmark");
46
+ const result = validateVisualDocument(doc);
47
+ if (!result.ok) throw new Error(result.issues.map((i) => `${i.path}: ${i.message}`).join("\n"));
48
+ ```
49
+
50
+ With CLI when available:
51
+
52
+ ```bash
53
+ node bin/sketchmark.cjs validate path/to/document.visual.json
54
+ ```
55
+
56
+ ## Render
57
+
58
+ Render a frame:
59
+
60
+ ```bash
61
+ node bin/sketchmark.cjs render path/to/document.visual.json --time 1 --out .tmp/preview.svg
62
+ ```
63
+
64
+ Preview/export commands may vary by package version. Check:
65
+
66
+ ```bash
67
+ node bin/sketchmark.cjs --help
68
+ ```
69
+
70
+ Create a reusable embed in code:
71
+
72
+ ```js
73
+ const { render } = require("sketchmark");
74
+
75
+ const html = render.embedHtml(doc, {
76
+ title: "Agent Preview",
77
+ maxFrames: 180
78
+ });
79
+ ```
80
+
81
+ Render or edit from a standalone Node project with the public package API:
82
+
83
+ ```js
84
+ const { render, edit } = require("sketchmark");
85
+
86
+ const svg = render.svg(doc, { time: 1 });
87
+ const nextDoc = edit.setProperty(doc, "element-id", "x", 120);
88
+ const keyedDoc = edit.setKeyframe(nextDoc, "element-id", "opacity", 0.5, 1);
89
+ ```
90
+
91
+ For explicit subpath imports:
92
+
93
+ ```js
94
+ const render = require("sketchmark/render");
95
+ const edit = require("sketchmark/edit");
96
+ const { editorHtml } = require("sketchmark/editor");
97
+ const { previewHtml } = require("sketchmark/preview");
98
+ ```
99
+
100
+ Create the same output from a browser host:
101
+
102
+ ```js
103
+ import { exportVisualInBrowser } from "sketchmark/browser-export";
104
+
105
+ await exportVisualInBrowser(doc, {
106
+ format: "embed",
107
+ title: "Agent Preview",
108
+ sourceDocument: doc
109
+ });
110
+ ```
111
+
112
+ ## Edit
113
+
114
+ For small edits:
115
+
116
+ 1. Find element by `id`.
117
+ 2. Patch only the needed properties.
118
+ 3. Preserve unrelated timelines.
119
+ 4. Validate.
120
+ 5. Render the changed frame.
121
+
122
+ For large edits:
123
+
124
+ 1. Update the generator.
125
+ 2. Regenerate the `.visual.json`.
126
+ 3. Validate.
127
+ 4. Render preview frames.
128
+
129
+ For new repo examples:
130
+
131
+ 1. Add `examples/make-name.cjs` or update an existing generator.
132
+ 2. Generate the derived `.visual.json` and any embed demo artifacts.
133
+ 3. Validate and spot-check the rendered result.
134
+
135
+ ## Preview
136
+
137
+ - SVG frame preview checks geometry, text, and paint.
138
+ - HTML preview checks animation playback when available.
139
+ - Embed preview is the preferred agent-friendly output: one HTML string, no server route, play/pause UI, scrubber, and export buttons.
140
+ - For host-agnostic embeds, keep the HTML self-contained: inline scripts, inline styles, and no CDN or runtime network dependency.
141
+ - Avoid module-script or blob/object-URL imports inside the embed. Some hosts rewrite or block blob URLs.
142
+ - Avoid relying on `URL.createObjectURL()` for runtime-loaded assets like SVG frame rasterization. Prefer `data:` URLs or other inline forms.
143
+ - Assume the embed may run inside `iframe`, `srcdoc`, webview, sandboxed previews, or artifact hosts that intercept downloads and messaging.
144
+ - Keep host integration generic: optional `postMessage` events are fine, but the embed should not require Claude-specific globals or a custom parent API to render.
145
+ - Embed chrome defaults to a transparent outer background with light/dark-aware translucent controls, so it sits more naturally inside host UIs.
146
+ - Current embed exports are `svg`, `png`, `jpg`, `html`, `json`, and `mp4`.
147
+ - Mount embed HTML in an `iframe` with `srcdoc` or the equivalent host API.
148
+ - Use a generated `.embed.html` file and a host page with an `iframe` as the reference pair when you need parent-child messaging.
149
+ - Parent pages can send `sketchmark-play`, `sketchmark-pause`, `sketchmark-show`, and `sketchmark-export` with `postMessage`.
150
+ - The embed posts back `sketchmark-rendered` with `title`, `duration`, and `time`.
151
+ - Use `maxFrames` to trade file size for smoother motion.
152
+ - MP4 export inside the embed requires WebCodecs. Chrome and Edge are the safest targets.
153
+ - Editor preview checks property editing and timeline changes.
154
+ - Browser export is preferred for web deployments that cannot rely on server `ffmpeg` or `sharp`.
155
+
156
+ ## Debug
157
+
158
+ - Validate before rendering.
159
+ - Lower `maxFrames` if the embed HTML gets too large.
160
+ - Browser raster or MP4 export can fail on unsupported browsers or when external images block canvas export.
161
+ - Unknown timeline tracks are invalid.
162
+ - Timeline curve fields must be objects.
163
+ - `cornerRadius` is not kernel; use `clip.d`.
164
+ - Text alignment uses `align` and `valign`.
165
+ - Image crop uses `source.*`.
166
+ - Render the exact failing time.