nodality 1.1.8 → 1.1.9
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/bin/mcp-server.mjs +315 -0
- package/bin/nodality.js +16 -0
- package/dist/animator.cjs.js.LICENSE.txt +1 -1
- package/dist/animator.esm.js.LICENSE.txt +1 -1
- package/dist/audionew.cjs.js.LICENSE.txt +1 -1
- package/dist/audionew.esm.js.LICENSE.txt +1 -1
- package/dist/base.cjs.js.LICENSE.txt +1 -1
- package/dist/base.esm.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
- package/dist/bundle.umd.js.LICENSE.txt +1 -1
- package/dist/button.cjs.js.LICENSE.txt +1 -1
- package/dist/button.esm.js.LICENSE.txt +1 -1
- package/dist/card-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/card-getter.esm.js.LICENSE.txt +1 -1
- package/dist/center.cjs.js.LICENSE.txt +1 -1
- package/dist/center.esm.js.LICENSE.txt +1 -1
- package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
- package/dist/checkbox.esm.js.LICENSE.txt +1 -1
- package/dist/code.cjs.js.LICENSE.txt +1 -1
- package/dist/code.esm.js.LICENSE.txt +1 -1
- package/dist/container.cjs.js.LICENSE.txt +1 -1
- package/dist/container.esm.js.LICENSE.txt +1 -1
- package/dist/data-list.cjs.js.LICENSE.txt +1 -1
- package/dist/data-list.esm.js.LICENSE.txt +1 -1
- package/dist/designer.cjs.js.LICENSE.txt +1 -1
- package/dist/designer.esm.js.LICENSE.txt +1 -1
- package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
- package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
- package/dist/finalresult.esm.js.LICENSE.txt +1 -1
- package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-card.esm.js.LICENSE.txt +1 -1
- package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
- package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-row.esm.js.LICENSE.txt +1 -1
- package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
- package/dist/floating-input.esm.js.LICENSE.txt +1 -1
- package/dist/free.cjs.js.LICENSE.txt +1 -1
- package/dist/free.esm.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.cjs.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.esm.js.LICENSE.txt +1 -1
- package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
- package/dist/image-picker.esm.js.LICENSE.txt +1 -1
- package/dist/image.cjs.js.LICENSE.txt +1 -1
- package/dist/image.esm.js.LICENSE.txt +1 -1
- package/dist/index.cjs.js.LICENSE.txt +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.cjs.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.esm.js.LICENSE.txt +1 -1
- package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/link-getter.esm.js.LICENSE.txt +1 -1
- package/dist/link.cjs.js.LICENSE.txt +1 -1
- package/dist/link.esm.js.LICENSE.txt +1 -1
- package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
- package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
- package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/picker.cjs.js.LICENSE.txt +1 -1
- package/dist/picker.esm.js.LICENSE.txt +1 -1
- package/dist/progress.cjs.js.LICENSE.txt +1 -1
- package/dist/progress.esm.js.LICENSE.txt +1 -1
- package/dist/radio.cjs.js.LICENSE.txt +1 -1
- package/dist/radio.esm.js.LICENSE.txt +1 -1
- package/dist/range.cjs.js.LICENSE.txt +1 -1
- package/dist/range.esm.js.LICENSE.txt +1 -1
- package/dist/scroll-video.cjs.js.LICENSE.txt +1 -1
- package/dist/scroll-video.esm.js.LICENSE.txt +1 -1
- package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-bar.esm.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
- package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
- package/dist/spacer.cjs.js.LICENSE.txt +1 -1
- package/dist/spacer.esm.js.LICENSE.txt +1 -1
- package/dist/stack.cjs.js.LICENSE.txt +1 -1
- package/dist/stack.esm.js.LICENSE.txt +1 -1
- package/dist/stacker.cjs.js.LICENSE.txt +1 -1
- package/dist/stacker.esm.js.LICENSE.txt +1 -1
- package/dist/table.cjs.js.LICENSE.txt +1 -1
- package/dist/table.esm.js.LICENSE.txt +1 -1
- package/dist/text-field.cjs.js.LICENSE.txt +1 -1
- package/dist/text-field.esm.js.LICENSE.txt +1 -1
- package/dist/text.cjs.js.LICENSE.txt +1 -1
- package/dist/text.esm.js.LICENSE.txt +1 -1
- package/dist/theme.cjs.js.LICENSE.txt +1 -1
- package/dist/theme.esm.js.LICENSE.txt +1 -1
- package/dist/transform-anim.cjs.js.LICENSE.txt +1 -1
- package/dist/transform-anim.esm.js.LICENSE.txt +1 -1
- package/dist/ulist.cjs.js.LICENSE.txt +1 -1
- package/dist/ulist.esm.js.LICENSE.txt +1 -1
- package/dist/video.cjs.js.LICENSE.txt +1 -1
- package/dist/video.esm.js.LICENSE.txt +1 -1
- package/dist/wrap.cjs.js.LICENSE.txt +1 -1
- package/dist/wrap.esm.js.LICENSE.txt +1 -1
- package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
- package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
- package/layout/animator.js +1 -1
- package/layout/audio.js +1 -1
- package/layout/audionew.js +1 -1
- package/layout/base.js +1 -1
- package/layout/beta-desktop-bar.js +1 -1
- package/layout/beta-mobile-bar.js +1 -1
- package/layout/button.js +1 -1
- package/layout/center.js +1 -1
- package/layout/checkbox.js +1 -1
- package/layout/circle.js +1 -1
- package/layout/code.js +1 -1
- package/layout/container.js +1 -1
- package/layout/dropdown-2025.js +1 -1
- package/layout/flex-card.js +1 -1
- package/layout/flex-grid.js +1 -1
- package/layout/flex-row.js +1 -1
- package/layout/form-components/custom.js +1 -1
- package/layout/form-components/data-list.js +1 -1
- package/layout/form-components/floating-input.js +1 -1
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +1 -1
- package/layout/form-components/picker.js +1 -1
- package/layout/form-components/radio.js +1 -1
- package/layout/form-components/radiogroup.js +1 -1
- package/layout/form-components/range.js +1 -1
- package/layout/free.js +1 -1
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image.js +1 -1
- package/layout/index.js +1 -1
- package/layout/link.js +1 -1
- package/layout/list.js +1 -1
- package/layout/meta-adder.js +1 -1
- package/layout/modal-2025.js +1 -1
- package/layout/morph.js +1 -1
- package/layout/multiswitcher.js +1 -1
- package/layout/nav-bar.js +1 -1
- package/layout/nav-factor/custom-div.js +1 -1
- package/layout/new-nav-bar.js +1 -1
- package/layout/polygon.js +1 -1
- package/layout/prerender-site.js +1 -1
- package/layout/prerender.js +1 -1
- package/layout/progress.js +1 -1
- package/layout/row.js +1 -1
- package/layout/scroll-video.js +1 -1
- package/layout/side-bar.js +1 -1
- package/layout/side-nav-bar.js +1 -1
- package/layout/simple-bar.js +1 -1
- package/layout/slider-2025.js +1 -1
- package/layout/spacer.js +1 -1
- package/layout/stack.js +1 -1
- package/layout/svg.js +1 -1
- package/layout/switcher.js +1 -1
- package/layout/table.js +1 -1
- package/layout/text-field.js +1 -1
- package/layout/text.js +1 -1
- package/layout/ulist.js +1 -1
- package/layout/video.js +1 -1
- package/layout/wrap.js +1 -1
- package/layout/zoom-card.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/codegen.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +1 -1
- package/lib/element-mapper.js +1 -1
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/morph-node.js +1 -1
- package/lib/raster-inspect.js +1 -1
- package/lib/raster-ops.js +1 -1
- package/lib/raster-presets.js +1 -1
- package/lib/scroll-video.js +1 -1
- package/lib/seo.js +1 -1
- package/lib/stacker.js +1 -1
- package/lib/suggest.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- package/lib/transition.js +1 -1
- package/lib/validate-nodes.js +227 -0
- package/package.json +2 -1
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* nodality v1.1.9
|
|
3
|
+
* (c) 2026 Filip Vabrousek
|
|
4
|
+
* License: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/*!
|
|
8
|
+
* validate-nodes.js — check an `N` array before it is applied.
|
|
9
|
+
*
|
|
10
|
+
* The library already validates an op DEFINITION when it is registered
|
|
11
|
+
* (`validateRasterOp`), which catches a bad op author. Nothing checked a
|
|
12
|
+
* node INSTANCE — the thing a page, or an agent, actually writes. A
|
|
13
|
+
* misspelled op name, a parameter that belongs to a different op, a
|
|
14
|
+
* driver that does not exist: all of these were silent, and a silent
|
|
15
|
+
* no-op is the worst possible failure for a generator that cannot see
|
|
16
|
+
* the screen.
|
|
17
|
+
*
|
|
18
|
+
* The report shape is deliberately identical to the one `layout/morph.js`
|
|
19
|
+
* `validate()` returns — `{ ok, errors: [{ code, path, got, suggestions,
|
|
20
|
+
* valid }] }` — so that a consumer, human or agent, learns one shape and
|
|
21
|
+
* reads every diagnostic this library produces with it.
|
|
22
|
+
*
|
|
23
|
+
* Suggestions are the point. An agent that writes "dithr" should be told
|
|
24
|
+
* "dither" and repair itself in one turn, rather than receiving nothing
|
|
25
|
+
* and concluding the effect simply does not work.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import {
|
|
29
|
+
REGISTRY, RASTER_OP_NAMES, DRIVER_NAMES, RASTER_UNITS,
|
|
30
|
+
FRAMEWORK_DOC, EASING_NAMES,
|
|
31
|
+
} from "./raster-ops.js";
|
|
32
|
+
import { didYouMean, suggest } from "./suggest.js";
|
|
33
|
+
|
|
34
|
+
/** Node families, told apart exactly the way the runtime tells them apart. */
|
|
35
|
+
const familyOf = (node) => {
|
|
36
|
+
if (!node || typeof node !== "object") return "invalid";
|
|
37
|
+
const op = node.op;
|
|
38
|
+
if (typeof op === "string") return op === "morph" ? "morph" : "raster";
|
|
39
|
+
if (op && typeof op === "object" && typeof op.name === "string") return "design";
|
|
40
|
+
return "invalid";
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check an array of nodes against the registry.
|
|
45
|
+
*
|
|
46
|
+
* @param {Array} nodes the `N` array
|
|
47
|
+
* @param {Array} [elements] the `E` array; when given, `target` and a
|
|
48
|
+
* morph's `from`/`to` are checked to name ids that actually exist,
|
|
49
|
+
* which is the other half of the "silent no-op" problem: a correctly
|
|
50
|
+
* spelled op aimed at an element that is not there does nothing at all.
|
|
51
|
+
*/
|
|
52
|
+
export function validateNodes(nodes, elements) {
|
|
53
|
+
const errors = [];
|
|
54
|
+
const push = (code, path, got, suggestions, valid) => {
|
|
55
|
+
errors.push({
|
|
56
|
+
code, path, got,
|
|
57
|
+
suggestions: suggestions || [],
|
|
58
|
+
valid: valid || [],
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (!Array.isArray(nodes)) {
|
|
63
|
+
push("BAD_NODES", "nodes", nodes, [], ["an array of node objects"]);
|
|
64
|
+
return { ok: false, errors };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Ids declared by E, including children, since `target` may name any
|
|
68
|
+
// of them. Absent E, id checking is skipped rather than guessed at.
|
|
69
|
+
const ids = [];
|
|
70
|
+
const walk = (list) => {
|
|
71
|
+
if (!Array.isArray(list)) return;
|
|
72
|
+
for (const el of list) {
|
|
73
|
+
if (!el || typeof el !== "object") continue;
|
|
74
|
+
if (typeof el.id === "string") ids.push(el.id);
|
|
75
|
+
walk(el.children);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
if (elements !== undefined) walk(elements);
|
|
79
|
+
const idsKnown = elements !== undefined;
|
|
80
|
+
|
|
81
|
+
const checkTargets = (value, path) => {
|
|
82
|
+
if (value === undefined) return;
|
|
83
|
+
const list = Array.isArray(value) ? value : [value];
|
|
84
|
+
list.forEach((t, i) => {
|
|
85
|
+
const at = Array.isArray(value) ? `${path}[${i}]` : path;
|
|
86
|
+
if (typeof t !== "string") {
|
|
87
|
+
push("BAD_TARGET", at, t, [], ["an element id"]);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Ids are written bare in E and may be written with a leading
|
|
91
|
+
// "#" in a node; accept both rather than inventing a rule.
|
|
92
|
+
const bare = t.startsWith("#") ? t.slice(1) : t;
|
|
93
|
+
if (idsKnown && !ids.includes(bare)) {
|
|
94
|
+
push("UNKNOWN_TARGET", at, t, suggest(bare, ids), ids);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
nodes.forEach((node, i) => {
|
|
100
|
+
const path = `nodes[${i}]`;
|
|
101
|
+
const family = familyOf(node);
|
|
102
|
+
|
|
103
|
+
if (family === "invalid") {
|
|
104
|
+
push("BAD_NODE", path, node, [],
|
|
105
|
+
["{ op: \"<raster op>\" }", "{ op: { name: \"<design op>\" } }",
|
|
106
|
+
"{ op: \"morph\", from, to }"]);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
checkTargets(node.target, `${path}.target`);
|
|
111
|
+
|
|
112
|
+
if (family === "design") return; // design nodes carry their own vocabulary
|
|
113
|
+
|
|
114
|
+
if (family === "morph") {
|
|
115
|
+
// The morph node's own contract. `from` and `to` are what make
|
|
116
|
+
// it a morph; without them the node is inert.
|
|
117
|
+
if (typeof node.from !== "string") {
|
|
118
|
+
push("MISSING_FIELD", `${path}.from`, node.from, [],
|
|
119
|
+
["the id of the element that morphs"]);
|
|
120
|
+
} else {
|
|
121
|
+
checkTargets(node.from, `${path}.from`);
|
|
122
|
+
}
|
|
123
|
+
if (node.to === undefined) {
|
|
124
|
+
push("MISSING_FIELD", `${path}.to`, undefined, [],
|
|
125
|
+
["[\"id\", ...]", "{ \"Link label\": \"id\" }"]);
|
|
126
|
+
} else if (Array.isArray(node.to)) {
|
|
127
|
+
checkTargets(node.to, `${path}.to`);
|
|
128
|
+
} else if (node.to && typeof node.to === "object") {
|
|
129
|
+
for (const label in node.to) {
|
|
130
|
+
checkTargets(node.to[label], `${path}.to.${label}`);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
push("BAD_FIELD", `${path}.to`, node.to, [],
|
|
134
|
+
["an array of ids, or a map of link label to id"]);
|
|
135
|
+
}
|
|
136
|
+
if (node.duration !== undefined &&
|
|
137
|
+
(typeof node.duration !== "number" || !(node.duration > 0))) {
|
|
138
|
+
push("BAD_VALUE", `${path}.duration`, node.duration, [],
|
|
139
|
+
["a positive number of milliseconds"]);
|
|
140
|
+
}
|
|
141
|
+
if (node.effect !== undefined &&
|
|
142
|
+
typeof node.effect !== "string" && !Array.isArray(node.effect)) {
|
|
143
|
+
push("BAD_FIELD", `${path}.effect`, node.effect, [],
|
|
144
|
+
["a preset name, or an inline array of raster nodes"]);
|
|
145
|
+
}
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ── raster nodes ────────────────────────────────────────────
|
|
150
|
+
const def = REGISTRY[node.op];
|
|
151
|
+
if (!def) {
|
|
152
|
+
push("UNKNOWN_OP", `${path}.op`, node.op,
|
|
153
|
+
suggest(node.op, RASTER_OP_NAMES), RASTER_OP_NAMES);
|
|
154
|
+
return; // parameters cannot be judged without a definition
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const params = (def.doc && def.doc.params) || {};
|
|
158
|
+
const known = Object.keys(params);
|
|
159
|
+
const shared = Object.keys(FRAMEWORK_DOC);
|
|
160
|
+
|
|
161
|
+
for (const key in node) {
|
|
162
|
+
if (key === "op") continue;
|
|
163
|
+
if (shared.includes(key) || known.includes(key)) continue;
|
|
164
|
+
// A parameter that belongs to no op is a typo; one that belongs
|
|
165
|
+
// to a DIFFERENT op is the more interesting mistake, and the
|
|
166
|
+
// suggestion list covers both because it is drawn from this
|
|
167
|
+
// op's vocabulary plus the shared one.
|
|
168
|
+
push("UNKNOWN_PARAM", `${path}.${key}`, key,
|
|
169
|
+
suggest(key, known.concat(shared)), known.concat(shared));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (node.by !== undefined && !DRIVER_NAMES.includes(node.by)) {
|
|
173
|
+
push("UNKNOWN_DRIVER", `${path}.by`, node.by,
|
|
174
|
+
suggest(node.by, DRIVER_NAMES), DRIVER_NAMES);
|
|
175
|
+
}
|
|
176
|
+
if (node.ease !== undefined && typeof node.ease === "string" &&
|
|
177
|
+
!EASING_NAMES.includes(node.ease)) {
|
|
178
|
+
push("UNKNOWN_EASING", `${path}.ease`, node.ease,
|
|
179
|
+
suggest(node.ease, EASING_NAMES), EASING_NAMES);
|
|
180
|
+
}
|
|
181
|
+
if (node.side !== undefined && !["old", "new"].includes(node.side)) {
|
|
182
|
+
push("BAD_VALUE", `${path}.side`, node.side,
|
|
183
|
+
suggest(String(node.side), ["old", "new"]), ["old", "new"]);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return { ok: errors.length === 0, errors };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* The vocabulary, as data — what an agent needs before writing anything.
|
|
192
|
+
* Assembled from the registry rather than maintained separately, so it
|
|
193
|
+
* cannot drift from what the pipeline actually accepts.
|
|
194
|
+
*/
|
|
195
|
+
export function describeOps() {
|
|
196
|
+
const ops = RASTER_OP_NAMES.map((name) => {
|
|
197
|
+
const def = REGISTRY[name] || {};
|
|
198
|
+
const doc = def.doc || {};
|
|
199
|
+
const params = doc.params || {};
|
|
200
|
+
return {
|
|
201
|
+
op: name,
|
|
202
|
+
stage: Array.isArray(def.stage) ? def.stage : [def.stage].filter(Boolean),
|
|
203
|
+
summary: doc.summary || "",
|
|
204
|
+
params: Object.keys(params).map((p) => ({
|
|
205
|
+
name: p,
|
|
206
|
+
default: params[p].default,
|
|
207
|
+
unit: params[p].unit,
|
|
208
|
+
structural: !!params[p].structural,
|
|
209
|
+
summary: params[p].summary || "",
|
|
210
|
+
})),
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
return {
|
|
214
|
+
ops,
|
|
215
|
+
shared: Object.keys(FRAMEWORK_DOC).map((k) => ({
|
|
216
|
+
name: k,
|
|
217
|
+
default: FRAMEWORK_DOC[k].default,
|
|
218
|
+
unit: FRAMEWORK_DOC[k].unit,
|
|
219
|
+
summary: FRAMEWORK_DOC[k].summary || "",
|
|
220
|
+
})),
|
|
221
|
+
drivers: DRIVER_NAMES,
|
|
222
|
+
easings: EASING_NAMES,
|
|
223
|
+
units: RASTER_UNITS,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export { didYouMean };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodality",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "A lightweight library for declarative UI elements.",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"./morph": "./layout/morph.js",
|
|
29
29
|
"./presets": "./lib/raster-presets.js",
|
|
30
30
|
"./raster": "./lib/raster-ops.js",
|
|
31
|
+
"./validate": "./lib/validate-nodes.js",
|
|
31
32
|
"./inspect": "./lib/raster-inspect.js",
|
|
32
33
|
"./examples/*": "./examples/*.js",
|
|
33
34
|
"./transition": "./lib/transition.js",
|