nodality 1.2.11 → 1.3.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/bin/mcp-server.mjs +45 -0
- package/dist/animator.cjs.js +1 -1
- package/dist/animator.cjs.js.LICENSE.txt +1 -1
- package/dist/animator.esm.js +1 -1
- package/dist/animator.esm.js.LICENSE.txt +1 -1
- package/dist/audionew.cjs.js +1 -1
- package/dist/audionew.cjs.js.LICENSE.txt +1 -1
- package/dist/audionew.esm.js +1 -1
- package/dist/audionew.esm.js.LICENSE.txt +1 -1
- package/dist/base.cjs.js +1 -1
- package/dist/base.cjs.js.LICENSE.txt +1 -1
- package/dist/base.esm.js +1 -1
- package/dist/base.esm.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.cjs.js +1 -1
- package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.esm.js +1 -1
- package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.cjs.js +1 -1
- package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.esm.js +1 -1
- package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
- package/dist/bundle.umd.js +1 -1
- package/dist/bundle.umd.js.LICENSE.txt +1 -1
- package/dist/button.cjs.js +1 -1
- package/dist/button.cjs.js.LICENSE.txt +1 -1
- package/dist/button.esm.js +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 +1 -1
- package/dist/center.cjs.js.LICENSE.txt +1 -1
- package/dist/center.esm.js +1 -1
- package/dist/center.esm.js.LICENSE.txt +1 -1
- package/dist/checkbox.cjs.js +1 -1
- package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
- package/dist/checkbox.esm.js +1 -1
- package/dist/checkbox.esm.js.LICENSE.txt +1 -1
- package/dist/code.cjs.js +1 -1
- package/dist/code.cjs.js.LICENSE.txt +1 -1
- package/dist/code.esm.js +1 -1
- package/dist/code.esm.js.LICENSE.txt +1 -1
- package/dist/container.cjs.js +1 -1
- package/dist/container.cjs.js.LICENSE.txt +1 -1
- package/dist/container.esm.js +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 +1 -1
- package/dist/designer.cjs.js.LICENSE.txt +1 -1
- package/dist/designer.esm.js +1 -1
- package/dist/designer.esm.js.LICENSE.txt +1 -1
- package/dist/element-mapper.cjs.js +1 -1
- package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
- package/dist/element-mapper.esm.js +1 -1
- package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
- package/dist/finalresult.esm.js +1 -1
- package/dist/finalresult.esm.js.LICENSE.txt +1 -1
- package/dist/flex-card.cjs.js +1 -1
- package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-card.esm.js +1 -1
- package/dist/flex-card.esm.js.LICENSE.txt +1 -1
- package/dist/flex-grid.cjs.js +1 -1
- package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-grid.esm.js +1 -1
- package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
- package/dist/flex-row.cjs.js +1 -1
- package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-row.esm.js +1 -1
- package/dist/flex-row.esm.js.LICENSE.txt +1 -1
- package/dist/floating-input.cjs.js +1 -1
- package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
- package/dist/floating-input.esm.js +1 -1
- package/dist/floating-input.esm.js.LICENSE.txt +1 -1
- package/dist/free.cjs.js +1 -1
- package/dist/free.cjs.js.LICENSE.txt +1 -1
- package/dist/free.esm.js +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 +1 -1
- package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
- package/dist/image-picker.esm.js +1 -1
- package/dist/image-picker.esm.js.LICENSE.txt +1 -1
- package/dist/image.cjs.js +1 -1
- package/dist/image.cjs.js.LICENSE.txt +1 -1
- package/dist/image.esm.js +1 -1
- package/dist/image.esm.js.LICENSE.txt +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.LICENSE.txt +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.esm.js +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 +1 -1
- package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/link-getter.esm.js +1 -1
- package/dist/link-getter.esm.js.LICENSE.txt +1 -1
- package/dist/link.cjs.js +1 -1
- package/dist/link.cjs.js.LICENSE.txt +1 -1
- package/dist/link.esm.js +1 -1
- package/dist/link.esm.js.LICENSE.txt +1 -1
- package/dist/meta-adder.cjs.js +1 -1
- package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
- package/dist/meta-adder.esm.js +1 -1
- package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
- package/dist/modal-2025.cjs.js +1 -1
- package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/modal-2025.esm.js +1 -1
- package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.cjs.js +1 -1
- package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js +1 -1
- package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.cjs.js +1 -1
- package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.esm.js +1 -1
- package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/picker.cjs.js +1 -1
- package/dist/picker.cjs.js.LICENSE.txt +1 -1
- package/dist/picker.esm.js +1 -1
- package/dist/picker.esm.js.LICENSE.txt +1 -1
- package/dist/progress.cjs.js +1 -1
- package/dist/progress.cjs.js.LICENSE.txt +1 -1
- package/dist/progress.esm.js +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 +1 -1
- package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-bar.esm.js +1 -1
- package/dist/side-bar.esm.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.cjs.js +1 -1
- package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.esm.js +1 -1
- package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/simple-bar.cjs.js +1 -1
- package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/simple-bar.esm.js +1 -1
- package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
- package/dist/slider-2025.cjs.js +1 -1
- package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/slider-2025.esm.js +1 -1
- package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
- package/dist/spacer.cjs.js +1 -1
- package/dist/spacer.cjs.js.LICENSE.txt +1 -1
- package/dist/spacer.esm.js +1 -1
- package/dist/spacer.esm.js.LICENSE.txt +1 -1
- package/dist/stack.cjs.js +1 -1
- package/dist/stack.cjs.js.LICENSE.txt +1 -1
- package/dist/stack.esm.js +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 +1 -1
- package/dist/table.cjs.js.LICENSE.txt +1 -1
- package/dist/table.esm.js +1 -1
- package/dist/table.esm.js.LICENSE.txt +1 -1
- package/dist/text-field.cjs.js +1 -1
- package/dist/text-field.cjs.js.LICENSE.txt +1 -1
- package/dist/text-field.esm.js +1 -1
- package/dist/text-field.esm.js.LICENSE.txt +1 -1
- package/dist/text.cjs.js +1 -1
- package/dist/text.cjs.js.LICENSE.txt +1 -1
- package/dist/text.esm.js +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 +1 -1
- package/dist/ulist.cjs.js.LICENSE.txt +1 -1
- package/dist/ulist.esm.js +1 -1
- package/dist/ulist.esm.js.LICENSE.txt +1 -1
- package/dist/video.cjs.js +1 -1
- package/dist/video.cjs.js.LICENSE.txt +1 -1
- package/dist/video.esm.js +1 -1
- package/dist/video.esm.js.LICENSE.txt +1 -1
- package/dist/wrap.cjs.js +1 -1
- package/dist/wrap.cjs.js.LICENSE.txt +1 -1
- package/dist/wrap.esm.js +1 -1
- package/dist/wrap.esm.js.LICENSE.txt +1 -1
- package/dist/zoom-card.cjs.js +1 -1
- package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
- package/dist/zoom-card.esm.js +1 -1
- package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
- package/layout/animator.js +15 -2
- 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 +10 -3
- 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 +23 -4
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +5 -3
- 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 +15 -2
- 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 +11 -3
- package/layout/side-nav-bar.js +16 -3
- 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 +16 -1
- package/layout/text.js +28 -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/agent-surface.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/check-page.js +348 -0
- package/lib/codegen.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +64 -2
- package/lib/element-mapper.js +121 -23
- package/lib/element-params.generated.js +2 -2
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/morph-node.js +8 -1
- package/lib/normalize-spec.js +134 -0
- package/lib/parse-html.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/resolve-refs.js +121 -0
- 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 +111 -3
- package/lib/webmcp-adapter.js +1 -1
- package/package.json +3 -1
- package/schema.json +973 -12
- package/scripts/generate-schema.mjs +9 -1
- package/skills/nodality/SKILL.md +50 -0
package/lib/seo.js
CHANGED
package/lib/stacker.js
CHANGED
package/lib/suggest.js
CHANGED
package/lib/theme.js
CHANGED
package/lib/transform-anim.js
CHANGED
package/lib/transition.js
CHANGED
package/lib/validate-nodes.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* nodality v1.
|
|
2
|
+
* nodality v1.3.1
|
|
3
3
|
* (c) 2026 Filip Vabrousek
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -30,6 +30,8 @@ import {
|
|
|
30
30
|
FRAMEWORK_DOC, EASING_NAMES,
|
|
31
31
|
} from "./raster-ops.js";
|
|
32
32
|
import { presetNames, presetInfo } from "./raster-presets.js";
|
|
33
|
+
import { collectRefs, isRef, resolveRefs } from "./resolve-refs.js";
|
|
34
|
+
import { normalizeSpec, aliasConflicts, ALIASES } from "./normalize-spec.js";
|
|
33
35
|
import { ELEMENT_TYPES } from "./element-mapper.js";
|
|
34
36
|
import { ELEMENT_PARAM_NAMES } from "./element-params.generated.js";
|
|
35
37
|
import { didYouMean, suggest, levenshtein } from "./suggest.js";
|
|
@@ -161,7 +163,16 @@ export const CONTENT_SLOT = {
|
|
|
161
163
|
row: "children", form: "children", wrap: "children",
|
|
162
164
|
};
|
|
163
165
|
|
|
164
|
-
|
|
166
|
+
// Of the types that read `items`, which read the entries as ELEMENT SPECS
|
|
167
|
+
// rather than as data. `ulist` maps every object entry through the mapper;
|
|
168
|
+
// `cards`, `nav`, `sideNav` and `table` read theirs as data — nav entries are
|
|
169
|
+
// `{title, link}`, table entries are rows — and walking those as elements
|
|
170
|
+
// would report every correct page. Pinned against the mapper by a test rather
|
|
171
|
+
// than trusted, because a hand-kept table beside a mapper is exactly what
|
|
172
|
+
// drifted before 1.2.8.
|
|
173
|
+
export const SPEC_ITEMS = new Set(["ulist"]);
|
|
174
|
+
|
|
175
|
+
export function validateNodes(nodes, elements, defs) {
|
|
165
176
|
const errors = [];
|
|
166
177
|
const push = (code, path, got, suggestions, valid) => {
|
|
167
178
|
errors.push({
|
|
@@ -219,6 +230,42 @@ export function validateNodes(nodes, elements) {
|
|
|
219
230
|
// element whose `type` names nothing is not a silent no-op but a THROW
|
|
220
231
|
// from the mapper at render time, which reaches a generator as a stack
|
|
221
232
|
// trace rather than as a report it can repair from.
|
|
233
|
+
// Tier 3: a reference with no definition. Reported here as well as
|
|
234
|
+
// refused at render, because a report is repairable in one turn and a
|
|
235
|
+
// throw is not — the Stage 3 contract applied to the newest way of being
|
|
236
|
+
// wrong. `defs` is optional: without it references are left alone rather
|
|
237
|
+
// than all reported missing, since a caller may validate a page before
|
|
238
|
+
// deciding what to share.
|
|
239
|
+
if (defs && typeof defs === "object" && Array.isArray(elements)) {
|
|
240
|
+
const defined = Object.keys(defs);
|
|
241
|
+
for (const { name, path } of collectRefs(elements)) {
|
|
242
|
+
if (!Object.prototype.hasOwnProperty.call(defs, name)) {
|
|
243
|
+
push("DANGLING_REF", path, name, suggest(name, defined), defined);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Walk the RESOLVED tree when definitions are available. A reference
|
|
249
|
+
// with keys beside it is a real element once merged, and only the merged
|
|
250
|
+
// form can be checked: `{ $ref: "nav", itms: [] }` is a typo in an
|
|
251
|
+
// override, and validating the unexpanded reference would miss it —
|
|
252
|
+
// a silent no-op inside the mechanism built to remove silent no-ops.
|
|
253
|
+
let toWalk = (defs && typeof defs === "object" && Array.isArray(elements))
|
|
254
|
+
? resolveRefs(elements, defs)
|
|
255
|
+
: elements;
|
|
256
|
+
|
|
257
|
+
// An alias and its canonical name both present, disagreeing: one of them
|
|
258
|
+
// is going to be ignored. The author hears it here rather than finding it
|
|
259
|
+
// in the page.
|
|
260
|
+
for (const c of aliasConflicts(Array.isArray(elements) ? elements : [])) {
|
|
261
|
+
push("CONFLICTING_ALIAS", c.path, c.alias, [c.canonical],
|
|
262
|
+
[`"${c.alias}" is accepted as "${c.canonical}"; give one of them, not both`]);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Walk the normalised tree, so `{type:"img", src:"..."}` is checked as the
|
|
266
|
+
// element it actually becomes rather than reported as an unknown parameter.
|
|
267
|
+
if (Array.isArray(toWalk)) toWalk = normalizeSpec(toWalk);
|
|
268
|
+
|
|
222
269
|
if (idsKnown) {
|
|
223
270
|
const walkEls = (list, at) => {
|
|
224
271
|
if (!Array.isArray(list)) return;
|
|
@@ -239,6 +286,12 @@ export function validateNodes(nodes, elements) {
|
|
|
239
286
|
push("BAD_ELEMENT", p, el, [], ["{ type: \"<element type>\", ... }"]);
|
|
240
287
|
return;
|
|
241
288
|
}
|
|
289
|
+
// A reference is not an element and has no `type` by design.
|
|
290
|
+
// Its validity is whether the name resolves, which the
|
|
291
|
+
// DANGLING_REF pass above decides; reporting MISSING_FIELD
|
|
292
|
+
// here rejected every correct `$ref` there is.
|
|
293
|
+
if (isRef(el)) return;
|
|
294
|
+
|
|
242
295
|
if (typeof el.type !== "string") {
|
|
243
296
|
push("MISSING_FIELD", `${p}.type`, el.type, [],
|
|
244
297
|
["an element type, e.g. \"h1\", \"wrap\", \"nav\""]);
|
|
@@ -252,6 +305,19 @@ export function validateNodes(nodes, elements) {
|
|
|
252
305
|
// removed for `cards`, surviving one slot over. It is not a
|
|
253
306
|
// typo, so near-miss detection cannot reach it.
|
|
254
307
|
const wants = CONTENT_SLOT[el.type];
|
|
308
|
+
if (wants) {
|
|
309
|
+
// A content slot that is present but not a list. The
|
|
310
|
+
// mapper tests `Array.isArray(...) && length`, so
|
|
311
|
+
// `items: {…}` and `items: "x"` fall through to the
|
|
312
|
+
// placeholders — content declared, content ignored, no
|
|
313
|
+
// error. Same family as WRONG_CONTENT_SLOT: the key is
|
|
314
|
+
// right and the value cannot carry anything.
|
|
315
|
+
const given = el[wants];
|
|
316
|
+
if (given !== undefined && given !== null && !Array.isArray(given)) {
|
|
317
|
+
push("BAD_CONTENT_SHAPE", `${p}.${wants}`, given, [],
|
|
318
|
+
[`an array — "${el.type}" reads \`${wants}\` as a list`]);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
255
321
|
if (wants) {
|
|
256
322
|
const other = wants === "items" ? "children" : "items";
|
|
257
323
|
const filled = (v) => Array.isArray(v) ? v.length > 0 : v != null;
|
|
@@ -325,9 +391,51 @@ export function validateNodes(nodes, elements) {
|
|
|
325
391
|
if (Array.isArray(entry)) walkEls(entry, `${p}.items[${k}]`);
|
|
326
392
|
});
|
|
327
393
|
}
|
|
394
|
+
|
|
395
|
+
// Phase S7: an object entry with no `type`, in a slot whose
|
|
396
|
+
// entries ARE elements. `{type:"ulist", items:[{text:"Fast"}]}`
|
|
397
|
+
// validated clean and then threw from deep in the mapper —
|
|
398
|
+
// `Unknown element type "undefined"` — which is the Stage 3
|
|
399
|
+
// contract exactly inverted: validate-then-render handed the
|
|
400
|
+
// agent a stack trace in the one place the tool exists to
|
|
401
|
+
// prevent it.
|
|
402
|
+
//
|
|
403
|
+
// Tier 7 measured what that cost. The throw names every valid
|
|
404
|
+
// type and not one word about WHICH entry, so it is the same
|
|
405
|
+
// string for every fault of this shape on any page; the weaker
|
|
406
|
+
// of the two models repaired none of them and returned a
|
|
407
|
+
// byte-identical spec. The suggestion below therefore hands
|
|
408
|
+
// back the replacement rather than describing it.
|
|
409
|
+
//
|
|
410
|
+
// A string entry is the shorthand and stays valid.
|
|
411
|
+
if (SPEC_ITEMS.has(el.type) && Array.isArray(el.items)) {
|
|
412
|
+
el.items.forEach((entry, k) => {
|
|
413
|
+
const at = `${p}.items[${k}]`;
|
|
414
|
+
if (typeof entry === "string" || typeof entry === "number") return;
|
|
415
|
+
if (Array.isArray(entry)) return;
|
|
416
|
+
if (!entry || typeof entry !== "object") {
|
|
417
|
+
push("BAD_ELEMENT", at, entry, [],
|
|
418
|
+
["a string, or { type: \"<element type>\", ... }"]);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (isRef(entry)) return;
|
|
422
|
+
if (typeof entry.type !== "string") {
|
|
423
|
+
const text = ["text", "title", "label"]
|
|
424
|
+
.map((k2) => entry[k2]).find((v) => typeof v === "string");
|
|
425
|
+
push("MISSING_FIELD", `${at}.type`, entry.type,
|
|
426
|
+
text === undefined ? []
|
|
427
|
+
: [JSON.stringify(text),
|
|
428
|
+
`{ "type": "p", "text": ${JSON.stringify(text)} }`],
|
|
429
|
+
[`"${el.type}" reads each item as an element; a plain string is the shorthand`]);
|
|
430
|
+
} else if (!ELEMENT_TYPES.includes(entry.type)) {
|
|
431
|
+
push("UNKNOWN_ELEMENT_TYPE", `${at}.type`, entry.type,
|
|
432
|
+
suggest(entry.type, ELEMENT_TYPES), ELEMENT_TYPES);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
328
436
|
});
|
|
329
437
|
};
|
|
330
|
-
walkEls(
|
|
438
|
+
walkEls(toWalk, "elements");
|
|
331
439
|
}
|
|
332
440
|
|
|
333
441
|
nodes.forEach((node, i) => {
|
package/lib/webmcp-adapter.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodality",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "A lightweight library for declarative UI elements.",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
"./raster": "./lib/raster-ops.js",
|
|
34
34
|
"./validate": "./lib/validate-nodes.js",
|
|
35
35
|
"./parse": "./lib/parse-html.js",
|
|
36
|
+
"./refs": "./lib/resolve-refs.js",
|
|
37
|
+
"./normalize": "./lib/normalize-spec.js",
|
|
36
38
|
"./inspect": "./lib/raster-inspect.js",
|
|
37
39
|
"./examples/*": "./examples/*.js",
|
|
38
40
|
"./transition": "./lib/transition.js",
|