sketchmark 2.0.0 → 2.1.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.
- package/README.md +274 -188
- package/bin/editor-ui.cjs +2285 -0
- package/bin/preview-ui.cjs +74 -0
- package/bin/sketchmark.cjs +648 -2008
- package/dist/src/animatable.d.ts +21 -0
- package/dist/src/animatable.js +439 -0
- package/dist/src/builders/index.d.ts +1 -11
- package/dist/src/builders/index.js +1 -19
- package/dist/src/diagnostics.js +1 -64
- package/dist/src/edit.d.ts +27 -0
- package/dist/src/edit.js +162 -0
- package/dist/src/index.d.ts +4 -13
- package/dist/src/index.js +4 -13
- package/dist/src/keyframes.d.ts +48 -0
- package/dist/src/keyframes.js +182 -0
- package/dist/src/motion.d.ts +4 -0
- package/dist/src/motion.js +262 -0
- package/dist/src/normalize.js +120 -151
- package/dist/src/presets/characters.d.ts +15 -0
- package/dist/src/presets/characters.js +113 -0
- package/dist/src/presets/compose.d.ts +5 -0
- package/dist/src/presets/compose.js +80 -0
- package/dist/src/presets/effects.d.ts +40 -0
- package/dist/src/presets/effects.js +79 -0
- package/dist/src/presets/helpers.d.ts +33 -0
- package/dist/src/presets/helpers.js +165 -0
- package/dist/src/presets/index.d.ts +9 -0
- package/dist/src/presets/index.js +48 -0
- package/dist/src/presets/motions.d.ts +33 -0
- package/dist/src/presets/motions.js +75 -0
- package/dist/src/presets/scenes.d.ts +35 -0
- package/dist/src/presets/scenes.js +134 -0
- package/dist/src/presets/shapes.d.ts +71 -0
- package/dist/src/presets/shapes.js +96 -0
- package/dist/src/presets/transitions.d.ts +29 -0
- package/dist/src/presets/transitions.js +113 -0
- package/dist/src/presets/types.d.ts +34 -0
- package/dist/src/presets/types.js +2 -0
- package/dist/src/render/html.js +1 -4
- package/dist/src/render/svg.d.ts +2 -2
- package/dist/src/render/svg.js +86 -82
- package/dist/src/render/three-html.js +67 -113
- package/dist/src/scenes.js +1 -0
- package/dist/src/schema.js +218 -280
- package/dist/src/shapes/builtins.js +11 -47
- package/dist/src/shapes/common.js +12 -11
- package/dist/src/shapes/registry.d.ts +0 -1
- package/dist/src/shapes/registry.js +0 -4
- package/dist/src/shapes/types.d.ts +1 -3
- package/dist/src/types.d.ts +57 -288
- package/dist/src/utils.d.ts +2 -11
- package/dist/src/utils.js +13 -70
- package/dist/src/validate.js +321 -275
- package/dist/tests/run.js +576 -510
- package/package.json +46 -52
- package/schema/visual.schema.json +1086 -930
package/README.md
CHANGED
|
@@ -1,188 +1,274 @@
|
|
|
1
|
-
# Sketchmark
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
The canonical
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
1
|
+
# Sketchmark
|
|
2
|
+
|
|
3
|
+
Sketchmark is currently a **pure 2D render kernel**.
|
|
4
|
+
|
|
5
|
+
The canonical JSON contains only renderable atoms:
|
|
6
|
+
|
|
7
|
+
- `path`
|
|
8
|
+
- `text`
|
|
9
|
+
- `image`
|
|
10
|
+
- `point`
|
|
11
|
+
- `group`
|
|
12
|
+
|
|
13
|
+
Everything else, including rectangles, circles, arrows, diagrams, charts, scenes, decks, 3D, and walking cycles, belongs above the kernel and compiles down to this format. Sketchmark ships an official `presets` layer for common reusable authoring helpers.
|
|
14
|
+
|
|
15
|
+
Reference docs:
|
|
16
|
+
|
|
17
|
+
- [Kernel Spec](./KERNEL_SPEC.md)
|
|
18
|
+
- [Animatable Property Matrix](./ANIMATABLE_MATRIX.md)
|
|
19
|
+
- [Presets](./PRESETS.md)
|
|
20
|
+
- [Packs](./PACKS.md)
|
|
21
|
+
- [What Needs Improvement](./WHAT_NEEDS_IMPROVEMENT.md)
|
|
22
|
+
|
|
23
|
+
## Kernel Document
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"version": 1,
|
|
28
|
+
"canvas": {
|
|
29
|
+
"width": 640,
|
|
30
|
+
"height": 360,
|
|
31
|
+
"background": "#f8fafc",
|
|
32
|
+
"duration": 2,
|
|
33
|
+
"fps": 30
|
|
34
|
+
},
|
|
35
|
+
"elements": [
|
|
36
|
+
{
|
|
37
|
+
"id": "line",
|
|
38
|
+
"type": "path",
|
|
39
|
+
"d": "M 80 240 C 180 80 320 280 520 120",
|
|
40
|
+
"fill": "none",
|
|
41
|
+
"stroke": "#111827",
|
|
42
|
+
"strokeWidth": 5,
|
|
43
|
+
"strokeCap": "round"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "title",
|
|
47
|
+
"type": "text",
|
|
48
|
+
"text": "Render kernel",
|
|
49
|
+
"x": 320,
|
|
50
|
+
"y": 70,
|
|
51
|
+
"align": "center",
|
|
52
|
+
"valign": "middle",
|
|
53
|
+
"fontSize": 28,
|
|
54
|
+
"weight": 800,
|
|
55
|
+
"fill": "#0f172a"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Only `version`, `canvas`, and `elements` are canonical top-level fields.
|
|
62
|
+
|
|
63
|
+
## Timeline
|
|
64
|
+
|
|
65
|
+
Animation is element-local. Tuple keyframes are still valid, but editor-facing tools should prefer object keyframes because curves live on the outgoing segment:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"id": "label",
|
|
70
|
+
"type": "text",
|
|
71
|
+
"text": "Move",
|
|
72
|
+
"x": 40,
|
|
73
|
+
"y": 80,
|
|
74
|
+
"timeline": {
|
|
75
|
+
"start": 0.5,
|
|
76
|
+
"end": 2,
|
|
77
|
+
"tracks": {
|
|
78
|
+
"position": {
|
|
79
|
+
"keyframes": [
|
|
80
|
+
{
|
|
81
|
+
"time": 0,
|
|
82
|
+
"value": [40, 80],
|
|
83
|
+
"out": {
|
|
84
|
+
"type": "cubicBezier",
|
|
85
|
+
"x1": 0.42,
|
|
86
|
+
"y1": 0,
|
|
87
|
+
"x2": 0.58,
|
|
88
|
+
"y2": 1
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
{ "time": 1.5, "value": [260, 80] }
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"opacity": {
|
|
95
|
+
"keyframes": [[0, 0], [0.4, 1]]
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Track values may be numbers, strings, `[x,y]` points, same-length number arrays, string arrays, or JSON objects. Known kernel properties are type-checked more strictly than the broad schema shape. `position` maps to `x/y` for `path`, `point`, `text`, `image`, and `group`. Tracks can also define a fallback interpolation graph:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"keyframes": [[0, [0, 0]], [1, [100, 0]]],
|
|
107
|
+
"curve": {
|
|
108
|
+
"type": "graph",
|
|
109
|
+
"points": [[0, 0], [0.35, 0.08], [0.65, 0.92], [1, 1]]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The graph maps normalized time progress `x` to normalized value progress `y`. Kernel curves can be `graph`, `cubicBezier`, or `hold`. Segment resolution is: previous keyframe `out`, previous keyframe `interpolation`, next keyframe `in`, track `curve`, legacy `ease`, then linear. Named easing strings are still accepted as compatibility shorthands, but helpers/presets should prefer emitting explicit curves. There are no expressions, path followers, pose drivers, scenes, or 3D in this kernel pass.
|
|
115
|
+
|
|
116
|
+
Current known animatable properties include transform/layout (`position`, `x`, `y`, `rotation`, `scale`, `scaleX`, `scaleY`, `origin`, `width`, `height`, `opacity`), path data/drawing/style (`d`, `fill`, `stroke`, `strokeWidth`, caps/joins, `dashArray`, `dashOffset`, `drawStart`, `drawEnd`), text content/layout (`text`, `lines`, `align`, `valign`, `fontStyle`, typography sizing), image `src`/`fit`/`source.*`, clip/mask paths and opacity, filter effects (`effects.*`), whole paint switching, structured gradient internals such as `fill.to` or `fill.stops.0.color`, and pattern internals such as `fill.x`, `fill.width`, or `fill.opacity`.
|
|
117
|
+
|
|
118
|
+
Unknown timeline tracks are invalid in the frozen kernel. Rounded images should be authored above the kernel and compiled to `clip.d`; `cornerRadius` and editor metadata are intentionally not kernel fields.
|
|
119
|
+
|
|
120
|
+
## Keyframe Authoring
|
|
121
|
+
|
|
122
|
+
For AI or editor-style authoring, use visual snapshots and compile them down to kernel timelines:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { compileKeyframeStates, timelineCurvePreset } from "sketchmark";
|
|
126
|
+
|
|
127
|
+
const animated = compileKeyframeStates(document, [
|
|
128
|
+
{
|
|
129
|
+
time: 0,
|
|
130
|
+
set: {
|
|
131
|
+
card: { position: [80, 160], scale: 0.85, opacity: 0 }
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
time: 1,
|
|
136
|
+
set: {
|
|
137
|
+
card: {
|
|
138
|
+
position: {
|
|
139
|
+
value: [220, 120],
|
|
140
|
+
curve: timelineCurvePreset("ease-out")
|
|
141
|
+
},
|
|
142
|
+
scale: 1,
|
|
143
|
+
opacity: 1
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
]);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
This is an authoring adapter, not a new JSON schema feature. The compiled output is still only kernel elements with local timelines.
|
|
151
|
+
|
|
152
|
+
## Preset Layer
|
|
153
|
+
|
|
154
|
+
Presets are reusable authoring helpers that compile to pure kernel output. They are exported separately so the root package can stay kernel-focused:
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
const { applyPresetFragments, shapes, motions, effects } = require("sketchmark/presets");
|
|
158
|
+
|
|
159
|
+
const visual = applyPresetFragments(
|
|
160
|
+
{
|
|
161
|
+
version: 1,
|
|
162
|
+
canvas: { width: 960, height: 540, duration: 2, fps: 30 },
|
|
163
|
+
elements: []
|
|
164
|
+
},
|
|
165
|
+
[
|
|
166
|
+
shapes.roundedRect({
|
|
167
|
+
id: "card",
|
|
168
|
+
x: 80,
|
|
169
|
+
y: 80,
|
|
170
|
+
width: 260,
|
|
171
|
+
height: 120,
|
|
172
|
+
radius: 16,
|
|
173
|
+
fill: "#ffffff",
|
|
174
|
+
stroke: "#cbd5e1"
|
|
175
|
+
}),
|
|
176
|
+
motions.riseIn({ id: "card", from: [80, 120], to: [80, 80] }),
|
|
177
|
+
effects.dropShadow({ id: "card", dy: 10, blur: 24, opacity: 0.2 })
|
|
178
|
+
]
|
|
179
|
+
);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
The output `.visual.json` still contains only kernel elements and timelines. Official namespaces include `shapes`, `characters`, `motions`, `effects`, `transitions`, and `scenes`.
|
|
183
|
+
|
|
184
|
+
## CLI
|
|
185
|
+
|
|
186
|
+
Build first:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
npm run build
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Render:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
node bin/sketchmark.cjs render examples/basic.visual.json out.svg
|
|
196
|
+
node bin/sketchmark.cjs render examples/timeline.visual.json out.html --time 1
|
|
197
|
+
node bin/sketchmark.cjs render examples/timeline.visual.json out.mp4
|
|
198
|
+
node bin/sketchmark.cjs render examples/timeline.visual.json out.webm --fps 30
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Generate the key-pose walking example:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
node examples/make-keypose-walk.cjs
|
|
205
|
+
node bin/sketchmark.cjs preview examples/keypose-walk.visual.json
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Generate the key-pose cyclist example:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
node examples/make-keypose-cycle.cjs
|
|
212
|
+
node bin/sketchmark.cjs preview examples/keypose-cycle.visual.json
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Generate preset-layer examples:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
node examples/make-presets-demo.cjs
|
|
219
|
+
node examples/make-preset-character-motion.cjs
|
|
220
|
+
node bin/sketchmark.cjs preview examples/presets-demo.visual.json
|
|
221
|
+
node bin/sketchmark.cjs preview examples/preset-character-motion.visual.json
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Generate heavier real-world stress scenes:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
node examples/make-stress-city-traffic.cjs
|
|
228
|
+
node examples/make-stress-ops-dashboard.cjs
|
|
229
|
+
node examples/make-stress-airport-radar.cjs
|
|
230
|
+
|
|
231
|
+
node bin/sketchmark.cjs preview examples/stress-city-traffic.visual.json
|
|
232
|
+
node bin/sketchmark.cjs preview examples/stress-ops-dashboard.visual.json
|
|
233
|
+
node bin/sketchmark.cjs preview examples/stress-airport-radar.visual.json
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
These are intentionally dense (many elements/keyframes) to pressure test preview responsiveness.
|
|
237
|
+
|
|
238
|
+
Preview animated timelines in the browser:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
node bin/sketchmark.cjs preview examples/timeline.visual.json
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Open the tiny editor:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
node bin/sketchmark.cjs edit examples/keypose-walk.visual.json
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Lint:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
node bin/sketchmark.cjs lint examples/basic.visual.json
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Video export is an adapter, not a kernel feature. It samples the document timeline into SVG frames, rasterizes those frames, and hands them to `ffmpeg`. It requires `sharp` and `ffmpeg` to be available in the local environment.
|
|
257
|
+
|
|
258
|
+
## Public API
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
import {
|
|
262
|
+
validateVisualDocument,
|
|
263
|
+
compileKeyframeStates,
|
|
264
|
+
timelineCurvePreset,
|
|
265
|
+
resolveVisualFrame,
|
|
266
|
+
renderToSvg,
|
|
267
|
+
renderToHtml,
|
|
268
|
+
lintVisualDocument
|
|
269
|
+
} from "sketchmark";
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
The root package intentionally exports no builders, player, project loader, deck/sequence helpers, 3D renderer, or preset compiler.
|
|
273
|
+
|
|
274
|
+
The official preset authoring layer is available from `sketchmark/presets`, not the root kernel entrypoint.
|