sygnal 6.2.0 → 6.4.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.
- package/CHANGELOG.md +112 -0
- package/README.md +3 -1
- package/dist/ai.cjs.js +36 -0
- package/dist/ai.cjs.js.map +1 -1
- package/dist/ai.esm.js +1 -1
- package/dist/astro/index.cjs.js +69 -3
- package/dist/astro/index.cjs.js.map +1 -1
- package/dist/astro/index.mjs +69 -3
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/server.cjs.js +3 -3
- package/dist/astro/server.cjs.js.map +1 -1
- package/dist/astro/server.mjs +3 -3
- package/dist/astro/server.mjs.map +1 -1
- package/dist/diagnostics.cjs.js +211 -11
- package/dist/diagnostics.cjs.js.map +1 -1
- package/dist/diagnostics.esm.js +211 -11
- package/dist/diagnostics.esm.js.map +1 -1
- package/dist/guide/agent.md +7 -1
- package/dist/guide/ai-cards.md +319 -0
- package/dist/guide/ai-chat.md +4 -0
- package/dist/guide/ai-compose.md +881 -0
- package/dist/guide/ai-decisions.md +16 -0
- package/dist/guide/http.md +1 -0
- package/dist/guide/mcp-apps.md +59 -4
- package/dist/index.cjs.js +5704 -350
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +647 -10
- package/dist/index.esm.js +5694 -350
- package/dist/index.esm.js.map +1 -1
- package/dist/sygnal.min.js +1 -1
- package/dist/sygnal.min.js.map +1 -1
- package/dist/vike/config/package.json +1 -1
- package/dist/vike/onRenderClient.cjs.js +3 -2
- package/dist/vike/onRenderClient.cjs.js.map +1 -1
- package/dist/vike/onRenderClient.mjs +3 -2
- package/dist/vike/onRenderClient.mjs.map +1 -1
- package/dist/vite/plugin.cjs.js +69 -3
- package/dist/vite/plugin.cjs.js.map +1 -1
- package/dist/vite/plugin.mjs +69 -3
- package/dist/vite/plugin.mjs.map +1 -1
- package/llms.txt +7 -5
- package/package.json +2 -1
- package/src/ai.d.ts +642 -7
- package/src/ai.ts +6 -0
- package/src/collection.ts +2 -1
- package/src/core/instance.ts +6 -3
- package/src/core/markers/lazy.ts +7 -3
- package/src/core/markers/portal.ts +5 -2
- package/src/core/markers/suspense.ts +3 -2
- package/src/core/markers/transition.ts +6 -3
- package/src/core/registry.ts +9 -5
- package/src/cycle/dom/IsolateModule.ts +25 -22
- package/src/extra/ai/chat/behavior.ts +354 -81
- package/src/extra/ai/chat/driver.ts +7 -4
- package/src/extra/ai/compose/agent.ts +55 -0
- package/src/extra/ai/compose/ask.ts +147 -0
- package/src/extra/ai/compose/behavior.ts +183 -0
- package/src/extra/ai/compose/catalog.ts +211 -0
- package/src/extra/ai/compose/composed.ts +61 -0
- package/src/extra/ai/compose/decisions.ts +1649 -0
- package/src/extra/ai/compose/diag.ts +33 -0
- package/src/extra/ai/compose/index.ts +23 -0
- package/src/extra/ai/compose/layout.ts +441 -0
- package/src/extra/ai/compose/llm.ts +1120 -0
- package/src/extra/ai/compose/render.ts +159 -0
- package/src/extra/ai/compose/testing.ts +71 -0
- package/src/extra/ai/compose/types.ts +159 -0
- package/src/extra/ai/decide.ts +97 -1
- package/src/extra/ai/index.ts +6 -1
- package/src/extra/diagnostics/checks/dom.ts +10 -2
- package/src/extra/diagnostics/checks/next.ts +103 -3
- package/src/extra/diagnostics/checks/persist.ts +4 -2
- package/src/extra/diagnostics/checks/wiring.ts +14 -6
- package/src/extra/diagnostics/codes.ts +59 -0
- package/src/extra/fetchDriver.ts +58 -27
- package/src/extra/lens.ts +15 -0
- package/src/extra/pwa.ts +3 -1
- package/src/extra/reducers.ts +10 -4
- package/src/extra/ssr.ts +3 -3
- package/src/extra/testing.ts +2 -0
- package/src/extra/widget.ts +3 -3
- package/src/index.d.ts +50 -2
- package/src/index.ts +8 -0
- package/src/lazy.ts +3 -2
- package/src/portal.ts +5 -2
- package/src/pragma/index.ts +2 -1
- package/src/suspense.ts +5 -2
- package/src/switchable.ts +2 -1
- package/src/transition.ts +5 -2
- package/src/vike/onRenderClient.ts +3 -2
- package/src/vite/plugin.ts +63 -2
package/dist/diagnostics.esm.js
CHANGED
|
@@ -247,6 +247,13 @@ const CODE_TITLES = {
|
|
|
247
247
|
SYG423: 'Context change skipped a view whose output it changes',
|
|
248
248
|
SYG424: 'Duplicate Collection item id',
|
|
249
249
|
SYG425: 'isolatedState slice lacks initialState keys',
|
|
250
|
+
// PLAN-9 (D471): checks/next.ts; dev entry and sygnal-check
|
|
251
|
+
SYG426: 'Deprecated lowercase marker tag',
|
|
252
|
+
// checks/next.ts and sygnal-check: a component reference that is not a function (an import of
|
|
253
|
+
// a name the module doesn't export is undefined under Vitest)
|
|
254
|
+
SYG427: 'CHILD.select() of something that is not a component',
|
|
255
|
+
// PLAN-9 (D470): checks/next.ts; dev entry
|
|
256
|
+
SYG453: 'Two children with the same identity share one instance',
|
|
250
257
|
SYG601: "Retired in 6.0: Missing or invalid sources",
|
|
251
258
|
SYG602: 'Intent is not a function',
|
|
252
259
|
SYG603: 'Intent returned an invalid value',
|
|
@@ -310,6 +317,29 @@ const CODE_TITLES = {
|
|
|
310
317
|
// PLAN-6 A-2: experimentalExposeWebMcp (src/extra/ai/webmcp.ts; dev)
|
|
311
318
|
SYG674: 'WebMCP not available',
|
|
312
319
|
SYG676: 'WebMCP registerTool rejected',
|
|
320
|
+
// ---- PLAN-9 compose (A: src/extra/ai/compose/; dev, reported with the severity passed) ----
|
|
321
|
+
SYG161: 'Catalog container render is a component with a model',
|
|
322
|
+
SYG162: 'Catalog part with neither component nor render',
|
|
323
|
+
SYG250: 'Layout names an unknown part or slot',
|
|
324
|
+
SYG251: 'Invalid param value in a layout',
|
|
325
|
+
SYG252: 'Record param from() does not return an array of { value }',
|
|
326
|
+
SYG450: 'Catalog in names an unknown container or slot',
|
|
327
|
+
SYG451: 'Composed has no catalog or from is not a composition',
|
|
328
|
+
SYG452: 'Layout lists a node key twice',
|
|
329
|
+
SYG681: 'Compose backend option problem',
|
|
330
|
+
// PLAN-9 B-1/B-2: compose.decisions() (src/extra/ai/compose/decisions.ts; explicit severities)
|
|
331
|
+
SYG680: 'Part is LLM-only under a decision backend',
|
|
332
|
+
SYG682: 'Decision model answered outside the criteria',
|
|
333
|
+
// PLAN-9 B-3: compose.llm() (src/extra/ai/compose/llm.ts; the compose status becomes 'error')
|
|
334
|
+
SYG683: 'LLM layout invalid after repair',
|
|
335
|
+
// PLAN-9 X-2: static only (sygnal-check rules/syg253-catalog.js)
|
|
336
|
+
SYG253: 'Misspelled catalog declaration key',
|
|
337
|
+
SYG254: 'Catalog descriptions or options overlap',
|
|
338
|
+
// PLAN-9 H: chat client tools and ask (src/extra/ai/chat/behavior.ts, compose/ask.ts, compose/render.ts)
|
|
339
|
+
SYG160: 'Result part rendered outside a card',
|
|
340
|
+
SYG684: 'Client tool shadows an agent tool',
|
|
341
|
+
SYG685: 'Answer for a tool call that is not open',
|
|
342
|
+
SYG686: 'Ask catalog without a result part',
|
|
313
343
|
// PLAN-4 GS-3: a11y lane (static only, sygnal-check)
|
|
314
344
|
SYG701: 'Click listener on a non-interactive element',
|
|
315
345
|
SYG702: 'Form field without an accessible label',
|
|
@@ -426,6 +456,12 @@ const DEV_CODE_SEVERITY = {
|
|
|
426
456
|
SYG423: 'warn',
|
|
427
457
|
SYG424: 'warn',
|
|
428
458
|
SYG425: 'warn',
|
|
459
|
+
// PLAN-9 (checks/next.ts): D471 a lowercase <collection> / <switchable> tag (deprecated in 6.3.0)
|
|
460
|
+
SYG426: 'warn',
|
|
461
|
+
// checks/next.ts: CHILD.select(undefined), usually a missing export
|
|
462
|
+
SYG427: 'error',
|
|
463
|
+
// PLAN-9 (checks/next.ts): D470 key identity, two children with one identity
|
|
464
|
+
SYG453: 'warn',
|
|
429
465
|
SYG612: 'error',
|
|
430
466
|
// PLAN-4 D131 (element.ts, through the core bridge; a console warning in dev with diagnostics off)
|
|
431
467
|
SYG644: 'warn',
|
|
@@ -466,6 +502,16 @@ const DEV_CODE_SEVERITY = {
|
|
|
466
502
|
// PLAN-6 A-2 (experimentalExposeWebMcp reports them with an explicit severity)
|
|
467
503
|
SYG674: 'info',
|
|
468
504
|
SYG676: 'warn',
|
|
505
|
+
// PLAN-9 B-1/B-2 (compose.decisions() reports them with an explicit severity)
|
|
506
|
+
SYG680: 'info',
|
|
507
|
+
SYG682: 'warn',
|
|
508
|
+
// PLAN-9 B-3 (compose.llm)
|
|
509
|
+
SYG683: 'error',
|
|
510
|
+
// PLAN-9 H (chat client tools and ask; reported with the severity passed)
|
|
511
|
+
SYG160: 'warn',
|
|
512
|
+
SYG684: 'warn',
|
|
513
|
+
SYG685: 'warn',
|
|
514
|
+
SYG686: 'warn',
|
|
469
515
|
// PLAN-5 V-1: VirtualCollection (checks/virtual.ts, through the core bridge)
|
|
470
516
|
SYG430: 'warn',
|
|
471
517
|
SYG431: 'warn',
|
|
@@ -497,6 +543,19 @@ const DEV_CODE_SEVERITY = {
|
|
|
497
543
|
SYG153: 'warn',
|
|
498
544
|
SYG730: 'warn',
|
|
499
545
|
SYG731: 'warn',
|
|
546
|
+
// ---- PLAN-9 compose (A: src/extra/ai/compose/, reported with the severity passed, dev) ----
|
|
547
|
+
SYG161: 'error',
|
|
548
|
+
SYG162: 'error',
|
|
549
|
+
SYG250: 'warn',
|
|
550
|
+
SYG251: 'warn',
|
|
551
|
+
SYG252: 'warn',
|
|
552
|
+
SYG450: 'warn',
|
|
553
|
+
SYG451: 'warn',
|
|
554
|
+
SYG452: 'warn',
|
|
555
|
+
SYG681: 'error',
|
|
556
|
+
// PLAN-9 X-2: static only (sygnal-check); listed so the entry knows their titles
|
|
557
|
+
SYG253: 'warn',
|
|
558
|
+
SYG254: 'info',
|
|
500
559
|
};
|
|
501
560
|
function getCodeInfo(code) {
|
|
502
561
|
const severity = CODE_SEVERITY[code];
|
|
@@ -717,11 +776,20 @@ const underTest = (c) => {
|
|
|
717
776
|
const dom = c?.sources?.[c.DOMSourceName || 'DOM'];
|
|
718
777
|
return !!dom && typeof dom == 'object' && '_hub' in dom;
|
|
719
778
|
};
|
|
720
|
-
// G-620: an LLM / chat sink gets the chat driver's fix,
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
779
|
+
// G-620: the usual driver for a known sink name (an LLM / chat sink gets the chat driver's fix,
|
|
780
|
+
// SW the service worker's), the generic text for any other name
|
|
781
|
+
const DRIVER_FOR = [
|
|
782
|
+
[/^(LLM|CHAT|AI|ASSISTANT)$/, (s) => `run(App, { ${s}: makeChatDriver({ transport: openResponses({ baseURL: 'http://localhost:11434/v1', model: 'llama3.2' }) }) }) (from 'sygnal/ai'; uiMessageStream('/api/chat') for an AI SDK server)`],
|
|
783
|
+
[/^(SW|SERVICE_WORKER)$/, (s) => `run(App, { ${s}: makeServiceWorkerDriver('/sw.js', { enabled: import.meta.env.PROD }) }) (enabled: false keeps the driver, with no service worker, on a dev server)`],
|
|
784
|
+
[/^(HTTP|API|FETCH)$/, (s) => `run(App, { ${s}: makeFetchDriver() })`],
|
|
785
|
+
[/^(WS|SOCKET)$/, (s) => `run(App, { ${s}: makeSocketDriver() })`],
|
|
786
|
+
];
|
|
787
|
+
const driverFix = (sink) => {
|
|
788
|
+
const known = DRIVER_FOR.find(([re]) => re.test(sink));
|
|
789
|
+
return `Pass a driver named ${sink} to run(): ` +
|
|
790
|
+
(known ? known[1](sink) : `run(App, { ${sink}: makeFetchDriver() }) for HTTP, or driverFromAsync(fn) / your own driver`) +
|
|
791
|
+
`. Check the spelling against the drivers you pass`;
|
|
792
|
+
};
|
|
725
793
|
const wiringCheck = {
|
|
726
794
|
id: 'wiring',
|
|
727
795
|
onIntent(component, actionNames) {
|
|
@@ -1270,6 +1338,10 @@ onReset(() => {
|
|
|
1270
1338
|
});
|
|
1271
1339
|
const unref = (t) => { if (t && typeof t.unref === 'function')
|
|
1272
1340
|
t.unref(); return t; };
|
|
1341
|
+
/**
|
|
1342
|
+
* The view's source, plus the words sygnal/vite registered for the component (its module's and
|
|
1343
|
+
* its relative imports' string literals: markup a view helper draws), when it did
|
|
1344
|
+
*/
|
|
1273
1345
|
function viewSource(component) {
|
|
1274
1346
|
const view = component && component.view;
|
|
1275
1347
|
if (typeof view !== 'function')
|
|
@@ -1282,6 +1354,9 @@ function viewSource(component) {
|
|
|
1282
1354
|
catch (_) {
|
|
1283
1355
|
src = '';
|
|
1284
1356
|
}
|
|
1357
|
+
const registered = globalThis.__SYGNAL_VIEW_TOKENS__?.get?.(view);
|
|
1358
|
+
if (typeof registered == 'string')
|
|
1359
|
+
src += '\n' + registered;
|
|
1285
1360
|
viewTokens.set(view, src);
|
|
1286
1361
|
}
|
|
1287
1362
|
return src;
|
|
@@ -2926,7 +3001,8 @@ const persistCheck = {
|
|
|
2926
3001
|
const o = p.options, init = view.initialState;
|
|
2927
3002
|
if (!o || !init || typeof init != 'object')
|
|
2928
3003
|
return;
|
|
2929
|
-
|
|
3004
|
+
// a behavior's slice (`uses = { chat: chat() }`) is a state key too
|
|
3005
|
+
const keys = [...Object.keys(init), ...Object.keys(view.uses || {})];
|
|
2930
3006
|
for (const opt of ['pick', 'omit']) {
|
|
2931
3007
|
for (const k of Array.isArray(o[opt]) ? o[opt] : []) {
|
|
2932
3008
|
if (keys.includes(k) || !once(`SYG223:${name}:${opt}:${k}`))
|
|
@@ -3605,7 +3681,8 @@ function installInspect() {
|
|
|
3605
3681
|
* a Collection's viewTransitionName that isn't an identifier, the same name twice on the
|
|
3606
3682
|
* page after a patch, G-460: on rendered elements), SYG612 (D173: a form
|
|
3607
3683
|
* 6.0 removed, met at runtime; once per form and component, with a link to the migration
|
|
3608
|
-
* guide)
|
|
3684
|
+
* guide), SYG453 (PLAN-9, D470: two children with one identity share one instance), SYG426
|
|
3685
|
+
* (PLAN-9, D471: a lowercase <collection> / <switchable> tag, deprecated in 6.3.0).
|
|
3609
3686
|
*
|
|
3610
3687
|
* Only while diagnostics are on (the checks' own rule); production builds never load this.
|
|
3611
3688
|
*/
|
|
@@ -3639,6 +3716,18 @@ function removed(component, name, anchor, detail) {
|
|
|
3639
3716
|
data: { form: anchor, guide: `${MIGRATE}#${anchor}`, ...(detail ? { detail } : {}) },
|
|
3640
3717
|
});
|
|
3641
3718
|
}
|
|
3719
|
+
/** SYG427: CHILD.select(x) with no component (an import of a name the module doesn't export) */
|
|
3720
|
+
function notComponent(f, x) {
|
|
3721
|
+
if (!once(`SYG427:${f.name}`))
|
|
3722
|
+
return;
|
|
3723
|
+
const got = x === null ? 'null' : typeof x == 'object' ? 'an object' : String(x);
|
|
3724
|
+
devReport('SYG427', {
|
|
3725
|
+
component: f.name,
|
|
3726
|
+
message: `${f.name}'s intent calls CHILD.select(${got}): that is not a component, so it never emits`,
|
|
3727
|
+
fix: "Pass the child component itself, and check its import: a name its module doesn't export is undefined (Vitest runs on; the browser fails to link the module). Export it: export function Child() { … }",
|
|
3728
|
+
data: { got },
|
|
3729
|
+
});
|
|
3730
|
+
}
|
|
3642
3731
|
/** the removed forms a definition shows (statics, view arity, model keys), once per function */
|
|
3643
3732
|
let seenDefs = new WeakSet();
|
|
3644
3733
|
// G-332: resetChecks() forgets them (as the once() dedupe)
|
|
@@ -3678,6 +3767,101 @@ function removedTags(f, v, depth = 0) {
|
|
|
3678
3767
|
for (const k of kids)
|
|
3679
3768
|
removedTags(f, k, depth + 1);
|
|
3680
3769
|
}
|
|
3770
|
+
/**
|
|
3771
|
+
* PLAN-9 SYG453 (D470): two children of one view with the same identity (the same component and
|
|
3772
|
+
* `key`, else `id`; `sel::key` in the core) are one instance, rendered in both places. The core
|
|
3773
|
+
* doesn't look (0 production bytes): in the owner's injected vnode that instance's output, a
|
|
3774
|
+
* scoped root (`data.isolate` in the real DOM driver, a `___<scope>` class in the mock DOM), is
|
|
3775
|
+
* the same object twice. Its name and key come from the child whose DOM source has that scope.
|
|
3776
|
+
*/
|
|
3777
|
+
const scopeOfVnode = (n) => {
|
|
3778
|
+
const iso = n.data?.isolate;
|
|
3779
|
+
if (Array.isArray(iso))
|
|
3780
|
+
return iso.length ? iso[iso.length - 1]?.scope : undefined;
|
|
3781
|
+
const m = typeof n.sel == 'string' && /\.___([^.]+)/.exec(n.sel);
|
|
3782
|
+
return m ? m[1] : undefined;
|
|
3783
|
+
};
|
|
3784
|
+
const scopeOfSource = (dom) => {
|
|
3785
|
+
const ns = dom?.namespace;
|
|
3786
|
+
if (Array.isArray(ns))
|
|
3787
|
+
return ns[ns.length - 1]?.scope;
|
|
3788
|
+
const p = dom?._path;
|
|
3789
|
+
const m = Array.isArray(p) && /^\.___(.+)$/.exec(String(p[p.length - 1]));
|
|
3790
|
+
return m ? m[1] : undefined;
|
|
3791
|
+
};
|
|
3792
|
+
function sharedIdentity(iv, v) {
|
|
3793
|
+
const seen = new Set(), dup = new Set();
|
|
3794
|
+
const walk = (n, d) => {
|
|
3795
|
+
if (!n || typeof n != 'object' || d > 300)
|
|
3796
|
+
return;
|
|
3797
|
+
const sc = scopeOfVnode(n);
|
|
3798
|
+
if (sc !== undefined) {
|
|
3799
|
+
if (seen.has(n)) {
|
|
3800
|
+
dup.add(sc);
|
|
3801
|
+
return;
|
|
3802
|
+
}
|
|
3803
|
+
seen.add(n);
|
|
3804
|
+
}
|
|
3805
|
+
const kids = n.children;
|
|
3806
|
+
if (Array.isArray(kids))
|
|
3807
|
+
for (const k of kids)
|
|
3808
|
+
walk(k, d + 1);
|
|
3809
|
+
};
|
|
3810
|
+
walk(v, 0);
|
|
3811
|
+
if (!dup.size)
|
|
3812
|
+
return;
|
|
3813
|
+
const owner = iv.name;
|
|
3814
|
+
for (const sc of dup) {
|
|
3815
|
+
let child;
|
|
3816
|
+
try {
|
|
3817
|
+
child = iv.children().find((c) => scopeOfSource(c.sources?.DOM) === sc);
|
|
3818
|
+
}
|
|
3819
|
+
catch (_) { /* ignore */ }
|
|
3820
|
+
const name = child ? child.name : 'a child component';
|
|
3821
|
+
// the identity's own part of the child's uid (the owner's uid + '-' + its key, id or path)
|
|
3822
|
+
const key = child && typeof child.uid == 'string' && child.uid.startsWith(iv.uid + '-') ? child.uid.slice(iv.uid.length + 1) : undefined;
|
|
3823
|
+
if (!once(`SYG453:${owner}:${name}:${key ?? sc}`))
|
|
3824
|
+
continue;
|
|
3825
|
+
devReport('SYG453', {
|
|
3826
|
+
component: owner,
|
|
3827
|
+
message: `${owner} renders ${child ? `<${name}>` : name} in two places with the same identity${key !== undefined ? ` (key or id ${JSON.stringify(key)})` : ''}, so both places show one instance: it has one state, and the second tag's props replace the first's`,
|
|
3828
|
+
fix: `Give each <${child ? name : 'Child'}> a different key (or id) among its parent's children, e.g. key={item.id}; a key on a component is its identity`,
|
|
3829
|
+
data: { child: child ? name : undefined, key },
|
|
3830
|
+
});
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
/**
|
|
3834
|
+
* PLAN-9 SYG426 (D471): the lowercase host tags, `<collection>` / `<switchable>` (JSX string tags,
|
|
3835
|
+
* or `h('collection')`), deprecated in 6.3.0; the next major removes them (and registers the hosts
|
|
3836
|
+
* on first use, as Portal). The core doesn't look (0 production bytes): the instance's template
|
|
3837
|
+
* keeps a host marker after reconcile (only `pres` markers are rewritten), and the imported
|
|
3838
|
+
* components' markers carry their function in `data.m`, a string tag's don't. The template is
|
|
3839
|
+
* the raw instance's (`iv.i`: the InstanceView's own field, a dev entry of the same build reads it;
|
|
3840
|
+
* the vnode onRender gets has the hosts' output injected in their place). Once per tag.
|
|
3841
|
+
*/
|
|
3842
|
+
const HOST_TAGS = { collection: 'Collection', switchable: 'Switchable' };
|
|
3843
|
+
function lowercaseTags(iv) {
|
|
3844
|
+
const raw = iv.i;
|
|
3845
|
+
if (!raw?.kids?.size || !raw.tmpl)
|
|
3846
|
+
return;
|
|
3847
|
+
const walk = (n, d) => {
|
|
3848
|
+
if (!n || typeof n != 'object' || n.$p || d > 300)
|
|
3849
|
+
return;
|
|
3850
|
+
const name = typeof n.sel == 'string' && !n.data?.m && HOST_TAGS[n.sel];
|
|
3851
|
+
if (name && once(`SYG426:${n.sel}`))
|
|
3852
|
+
devReport('SYG426', {
|
|
3853
|
+
component: iv.name,
|
|
3854
|
+
message: `${iv.name} renders the lowercase <${n.sel}> tag, which is deprecated since Sygnal 6.3.0 and will be removed in the next major (it will then render an unknown <${n.sel}> element)`,
|
|
3855
|
+
fix: `import { ${name} } from 'sygnal' and write <${name} …> (sygnal-check --fix does it)`,
|
|
3856
|
+
data: { tag: n.sel, component: name },
|
|
3857
|
+
});
|
|
3858
|
+
const kids = n.children;
|
|
3859
|
+
if (Array.isArray(kids))
|
|
3860
|
+
for (const k of kids)
|
|
3861
|
+
walk(k, d + 1);
|
|
3862
|
+
};
|
|
3863
|
+
walk(raw.tmpl, 0);
|
|
3864
|
+
}
|
|
3681
3865
|
/** the instance fields the checks read from today's Component instances */
|
|
3682
3866
|
class Facade {
|
|
3683
3867
|
constructor(__next) {
|
|
@@ -3927,8 +4111,13 @@ function nextHooks(_api) {
|
|
|
3927
4111
|
const v = t[k];
|
|
3928
4112
|
if (k !== 'CHILD' || !v || typeof v.select != 'function')
|
|
3929
4113
|
return v;
|
|
3930
|
-
return { ...v, select: (x, ...r) => {
|
|
3931
|
-
|
|
4114
|
+
return { ...v, select: (x, ...r) => {
|
|
4115
|
+
if (typeof x == 'string')
|
|
4116
|
+
removed(f, f.name, 'child-select-name', `CHILD.select('${x}')`);
|
|
4117
|
+
else if (typeof x != 'function')
|
|
4118
|
+
notComponent(f, x);
|
|
4119
|
+
return v.select(x, ...r);
|
|
4120
|
+
} };
|
|
3932
4121
|
},
|
|
3933
4122
|
});
|
|
3934
4123
|
},
|
|
@@ -3938,8 +4127,19 @@ function nextHooks(_api) {
|
|
|
3938
4127
|
onRender(iv, vnode) {
|
|
3939
4128
|
const f = fac(iv);
|
|
3940
4129
|
H.onRender(f, vnode);
|
|
3941
|
-
if (on())
|
|
3942
|
-
|
|
4130
|
+
if (!on())
|
|
4131
|
+
return;
|
|
4132
|
+
removedTags(f, vnode);
|
|
4133
|
+
try {
|
|
4134
|
+
lowercaseTags(iv);
|
|
4135
|
+
}
|
|
4136
|
+
catch (_) { /* a check never breaks the app */ }
|
|
4137
|
+
// SYG453: only a view with children can render one twice
|
|
4138
|
+
if (iv.children().length)
|
|
4139
|
+
try {
|
|
4140
|
+
sharedIdentity(iv, vnode);
|
|
4141
|
+
}
|
|
4142
|
+
catch (_) { /* a check never breaks the app */ }
|
|
3943
4143
|
},
|
|
3944
4144
|
onReducer(iv, type, prev, next) {
|
|
3945
4145
|
H.onReducer(fac(iv), type, prev, next, 'STATE');
|