@gyral/core 0.1.0 → 0.3.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/LICENSE +1 -1
- package/NOTICE +1 -1
- package/README.md +9 -7
- package/dist/children.d.ts +5 -2
- package/dist/children.js +8 -3
- package/dist/children.js.map +1 -1
- package/dist/command.js +6 -0
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +21 -0
- package/dist/compiler/ast.js +145 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +38 -0
- package/dist/compiler/compile.js +129 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/hooks.d.ts +18 -0
- package/dist/compiler/hooks.js +186 -0
- package/dist/compiler/hooks.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +55 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- package/dist/compiler/scan.d.ts +31 -0
- package/dist/compiler/scan.js +152 -0
- package/dist/compiler/scan.js.map +1 -0
- package/dist/compiler/source.d.ts +34 -0
- package/dist/compiler/source.js +114 -0
- package/dist/compiler/source.js.map +1 -0
- package/dist/define.d.ts +2 -2
- package/dist/define.js +35 -334
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +5 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +1 -0
- package/dist/devtools-off.js +1 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +1 -0
- package/dist/devtools.js +3 -0
- package/dist/devtools.js.map +1 -1
- package/dist/drivers-scope.d.ts +1 -1
- package/dist/drivers-scope.js +1 -8
- package/dist/drivers-scope.js.map +1 -1
- package/dist/element-types.d.ts +5 -3
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +269 -0
- package/dist/element.js.map +1 -0
- package/dist/eslint/imports.d.ts +24 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +15 -0
- package/dist/eslint/index.js +15 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/locate.d.ts +33 -0
- package/dist/eslint/locate.js +132 -0
- package/dist/eslint/locate.js.map +1 -0
- package/dist/eslint/row-purity-rule.d.ts +2 -0
- package/dist/eslint/row-purity-rule.js +103 -0
- package/dist/eslint/row-purity-rule.js.map +1 -0
- package/dist/eslint/template-rule.d.ts +5 -0
- package/dist/eslint/template-rule.js +66 -0
- package/dist/eslint/template-rule.js.map +1 -0
- package/dist/features.d.ts +39 -0
- package/dist/features.js +2 -0
- package/dist/features.js.map +1 -0
- package/dist/focus.d.ts +9 -2
- package/dist/focus.js +17 -2
- package/dist/focus.js.map +1 -1
- package/dist/hooks/invalid.d.ts +14 -0
- package/dist/hooks/invalid.js +72 -0
- package/dist/hooks/invalid.js.map +1 -0
- package/dist/hooks/labelled-by.d.ts +13 -0
- package/dist/hooks/labelled-by.js +51 -0
- package/dist/hooks/labelled-by.js.map +1 -0
- package/dist/host-model.d.ts +48 -0
- package/dist/host-model.js +155 -0
- package/dist/host-model.js.map +1 -0
- package/dist/hydration-client.d.ts +9 -0
- package/dist/hydration-client.js +35 -0
- package/dist/hydration-client.js.map +1 -0
- package/dist/hydration.d.ts +13 -19
- package/dist/hydration.js +45 -45
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +9 -16
- package/dist/index.js +9 -16
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +31 -8
- package/dist/intent.js +82 -27
- package/dist/intent.js.map +1 -1
- package/dist/internal/interpreter.d.ts +7 -1
- package/dist/internal/interpreter.js +118 -73
- package/dist/internal/interpreter.js.map +1 -1
- package/dist/invokers-shim.d.ts +6 -0
- package/dist/invokers-shim.js +32 -0
- package/dist/invokers-shim.js.map +1 -0
- package/dist/invokers.d.ts +3 -5
- package/dist/invokers.js +11 -51
- package/dist/invokers.js.map +1 -1
- package/dist/islands.d.ts +0 -2
- package/dist/islands.js +4 -11
- package/dist/islands.js.map +1 -1
- package/dist/light-dom.d.ts +3 -52
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +66 -0
- package/dist/prop.js +22 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +52 -21
- package/dist/props.js +150 -34
- package/dist/props.js.map +1 -1
- package/dist/scheduler.d.ts +39 -0
- package/dist/scheduler.js +230 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/server-component.d.ts +10 -0
- package/dist/server-component.js +102 -0
- package/dist/server-component.js.map +1 -0
- package/dist/server-specs.d.ts +6 -0
- package/dist/server-specs.js +13 -0
- package/dist/server-specs.js.map +1 -0
- package/dist/server.d.ts +28 -0
- package/dist/server.js +50 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +10 -0
- package/dist/settled.js +40 -0
- package/dist/settled.js.map +1 -0
- package/dist/states.d.ts +3 -3
- package/dist/states.js +4 -7
- package/dist/states.js.map +1 -1
- package/dist/store-binding.d.ts +6 -3
- package/dist/store-binding.js +5 -6
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +6 -7
- package/dist/store-scope.js +11 -26
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +9 -2
- package/dist/store.js.map +1 -1
- package/dist/stores-provider.d.ts +2 -6
- package/dist/stores-provider.js +21 -55
- package/dist/stores-provider.js.map +1 -1
- package/dist/transitions.d.ts +5 -6
- package/dist/transitions.js +11 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +19 -23
- package/dist/types.js.map +1 -1
- package/dist/view/attributes.d.ts +6 -0
- package/dist/view/attributes.js +10 -0
- package/dist/view/attributes.js.map +1 -0
- package/dist/view/compiled.d.ts +1 -0
- package/dist/view/compiled.js +6 -0
- package/dist/view/compiled.js.map +1 -0
- package/dist/view/dev-off.d.ts +1 -0
- package/dist/view/dev-off.js +4 -0
- package/dist/view/dev-off.js.map +1 -0
- package/dist/view/dev.d.ts +1 -0
- package/dist/view/dev.js +5 -0
- package/dist/view/dev.js.map +1 -0
- package/dist/view/flags.d.ts +1 -0
- package/dist/view/flags.js +4 -0
- package/dist/view/flags.js.map +1 -0
- package/dist/view/index.d.ts +21 -0
- package/dist/view/index.js +21 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/normalize/check.d.ts +20 -0
- package/dist/view/normalize/check.js +78 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +13 -0
- package/dist/view/normalize/emit.js +136 -0
- package/dist/view/normalize/emit.js.map +1 -0
- package/dist/view/normalize/entities.d.ts +4 -0
- package/dist/view/normalize/entities.js +38 -0
- package/dist/view/normalize/entities.js.map +1 -0
- package/dist/view/normalize/errors.d.ts +9 -0
- package/dist/view/normalize/errors.js +19 -0
- package/dist/view/normalize/errors.js.map +1 -0
- package/dist/view/normalize/id.d.ts +7 -0
- package/dist/view/normalize/id.js +48 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +15 -0
- package/dist/view/normalize/normalize.js +36 -0
- package/dist/view/normalize/normalize.js.map +1 -0
- package/dist/view/normalize/repairs.d.ts +24 -0
- package/dist/view/normalize/repairs.js +166 -0
- package/dist/view/normalize/repairs.js.map +1 -0
- package/dist/view/normalize/rules.d.ts +30 -0
- package/dist/view/normalize/rules.js +90 -0
- package/dist/view/normalize/rules.js.map +1 -0
- package/dist/view/normalize/shape.d.ts +5 -0
- package/dist/view/normalize/shape.js +38 -0
- package/dist/view/normalize/shape.js.map +1 -0
- package/dist/view/normalize/source.d.ts +13 -0
- package/dist/view/normalize/source.js +34 -0
- package/dist/view/normalize/source.js.map +1 -0
- package/dist/view/normalize/tag-states.d.ts +23 -0
- package/dist/view/normalize/tag-states.js +192 -0
- package/dist/view/normalize/tag-states.js.map +1 -0
- package/dist/view/normalize/tokenizer.d.ts +5 -0
- package/dist/view/normalize/tokenizer.js +233 -0
- package/dist/view/normalize/tokenizer.js.map +1 -0
- package/dist/view/normalize/tokens.d.ts +51 -0
- package/dist/view/normalize/tokens.js +24 -0
- package/dist/view/normalize/tokens.js.map +1 -0
- package/dist/view/normalize/tree.d.ts +59 -0
- package/dist/view/normalize/tree.js +190 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +126 -0
- package/dist/view/normalize/types.js +26 -0
- package/dist/view/normalize/types.js.map +1 -0
- package/dist/view/normalize/whitespace.d.ts +2 -0
- package/dist/view/normalize/whitespace.js +182 -0
- package/dist/view/normalize/whitespace.js.map +1 -0
- package/dist/view/prepare-stub.d.ts +3 -0
- package/dist/view/prepare-stub.js +7 -0
- package/dist/view/prepare-stub.js.map +1 -0
- package/dist/view/prepare.d.ts +8 -0
- package/dist/view/prepare.js +57 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +63 -0
- package/dist/view/registry.js +19 -0
- package/dist/view/registry.js.map +1 -0
- package/dist/view/render/adopt-attr.d.ts +14 -0
- package/dist/view/render/adopt-attr.js +77 -0
- package/dist/view/render/adopt-attr.js.map +1 -0
- package/dist/view/render/adopt-plan.d.ts +10 -0
- package/dist/view/render/adopt-plan.js +26 -0
- package/dist/view/render/adopt-plan.js.map +1 -0
- package/dist/view/render/adopt.d.ts +3 -0
- package/dist/view/render/adopt.js +269 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +61 -0
- package/dist/view/render/attr-parts.js +229 -0
- package/dist/view/render/attr-parts.js.map +1 -0
- package/dist/view/render/child-part.d.ts +51 -0
- package/dist/view/render/child-part.js +170 -0
- package/dist/view/render/child-part.js.map +1 -0
- package/dist/view/render/dev-check.d.ts +12 -0
- package/dist/view/render/dev-check.js +122 -0
- package/dist/view/render/dev-check.js.map +1 -0
- package/dist/view/render/hook-part.d.ts +3 -0
- package/dist/view/render/hook-part.js +20 -0
- package/dist/view/render/hook-part.js.map +1 -0
- package/dist/view/render/hooks.d.ts +40 -0
- package/dist/view/render/hooks.js +46 -0
- package/dist/view/render/hooks.js.map +1 -0
- package/dist/view/render/hydrate.d.ts +10 -0
- package/dist/view/render/hydrate.js +33 -0
- package/dist/view/render/hydrate.js.map +1 -0
- package/dist/view/render/instance.d.ts +33 -0
- package/dist/view/render/instance.js +107 -0
- package/dist/view/render/instance.js.map +1 -0
- package/dist/view/render/list.d.ts +20 -0
- package/dist/view/render/list.js +156 -0
- package/dist/view/render/list.js.map +1 -0
- package/dist/view/render/mismatch.d.ts +10 -0
- package/dist/view/render/mismatch.js +53 -0
- package/dist/view/render/mismatch.js.map +1 -0
- package/dist/view/render/nodes.d.ts +10 -0
- package/dist/view/render/nodes.js +37 -0
- package/dist/view/render/nodes.js.map +1 -0
- package/dist/view/render/place.d.ts +18 -0
- package/dist/view/render/place.js +69 -0
- package/dist/view/render/place.js.map +1 -0
- package/dist/view/render/plan.d.ts +26 -0
- package/dist/view/render/plan.js +124 -0
- package/dist/view/render/plan.js.map +1 -0
- package/dist/view/render/raw.d.ts +18 -0
- package/dist/view/render/raw.js +68 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +12 -0
- package/dist/view/render/render.js +60 -0
- package/dist/view/render/render.js.map +1 -0
- package/dist/view/render/reorder.d.ts +4 -0
- package/dist/view/render/reorder.js +101 -0
- package/dist/view/render/reorder.js.map +1 -0
- package/dist/view/render/rows.d.ts +23 -0
- package/dist/view/render/rows.js +95 -0
- package/dist/view/render/rows.js.map +1 -0
- package/dist/view/render/seen.d.ts +11 -0
- package/dist/view/render/seen.js +17 -0
- package/dist/view/render/seen.js.map +1 -0
- package/dist/view/render/values.d.ts +29 -0
- package/dist/view/render/values.js +13 -0
- package/dist/view/render/values.js.map +1 -0
- package/dist/view/render/warn.d.ts +14 -0
- package/dist/view/render/warn.js +69 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +9 -0
- package/dist/view/server/component.js +42 -0
- package/dist/view/server/component.js.map +1 -0
- package/dist/view/server/escape.d.ts +10 -0
- package/dist/view/server/escape.js +34 -0
- package/dist/view/server/escape.js.map +1 -0
- package/dist/view/server/index.d.ts +28 -0
- package/dist/view/server/index.js +72 -0
- package/dist/view/server/index.js.map +1 -0
- package/dist/view/server/sha256.d.ts +2 -0
- package/dist/view/server/sha256.js +75 -0
- package/dist/view/server/sha256.js.map +1 -0
- package/dist/view/server/tags.d.ts +57 -0
- package/dist/view/server/tags.js +121 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +16 -0
- package/dist/view/server/values.js +86 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +16 -0
- package/dist/view/server/writer.js +155 -0
- package/dist/view/server/writer.js.map +1 -0
- package/dist/view/styles.d.ts +25 -0
- package/dist/view/styles.js +58 -0
- package/dist/view/styles.js.map +1 -0
- package/dist/view/template-element.d.ts +3 -0
- package/dist/view/template-element.js +25 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +21 -0
- package/dist/view/template.js +30 -0
- package/dist/view/template.js.map +1 -0
- package/dist/vite.d.ts +45 -6
- package/dist/vite.js +150 -25
- package/dist/vite.js.map +1 -1
- package/package.json +41 -7
- package/dist/accessible-name.d.ts +0 -19
- package/dist/accessible-name.js +0 -56
- package/dist/accessible-name.js.map +0 -1
- package/dist/element-directive.d.ts +0 -20
- package/dist/element-directive.js +0 -31
- package/dist/element-directive.js.map +0 -1
- package/dist/internal/runtime.d.ts +0 -7
- package/dist/internal/runtime.js +0 -8
- package/dist/internal/runtime.js.map +0 -1
- package/dist/invalid.d.ts +0 -21
- package/dist/invalid.js +0 -70
- package/dist/invalid.js.map +0 -1
- package/dist/live-boolean.d.ts +0 -22
- package/dist/live-boolean.js +0 -34
- package/dist/live-boolean.js.map +0 -1
- package/dist/styles.d.ts +0 -12
- package/dist/styles.js +0 -11
- package/dist/styles.js.map +0 -1
- package/dist/textarea.d.ts +0 -26
- package/dist/textarea.js +0 -85
- package/dist/textarea.js.map +0 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// `raw(html)` (view/02-bindings.md "`raw(html)`"): trusted markup parsed in a child hole, kept
|
|
2
|
+
// as a node range after a start anchor and re-parsed only when the string changes. Its result
|
|
3
|
+
// carries `commitRaw`, so apps that never call `raw` don't bundle this module.
|
|
4
|
+
import { DEV } from '#view-dev';
|
|
5
|
+
import { EMPTY, RAW } from './child-part.js';
|
|
6
|
+
import { removeRange } from './nodes.js';
|
|
7
|
+
import { report } from './seen.js';
|
|
8
|
+
import { MARKUP } from './values.js';
|
|
9
|
+
import { warnRaw } from './warn.js';
|
|
10
|
+
/** Parsed `raw()` markup: the start anchor, the last node, and the string. */
|
|
11
|
+
export class RawRange {
|
|
12
|
+
constructor(start, end, html) {
|
|
13
|
+
this.start = start;
|
|
14
|
+
this.end = end;
|
|
15
|
+
this.html = html;
|
|
16
|
+
}
|
|
17
|
+
first() {
|
|
18
|
+
return this.start;
|
|
19
|
+
}
|
|
20
|
+
last() {
|
|
21
|
+
return this.end;
|
|
22
|
+
}
|
|
23
|
+
remove() {
|
|
24
|
+
removeRange(this.start, this.end);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
let parser;
|
|
28
|
+
/** `html` parsed by a <template> (its content is reused: read it before the next call). */
|
|
29
|
+
export function parse(html) {
|
|
30
|
+
parser ??= document.createElement('template');
|
|
31
|
+
parser.innerHTML = html;
|
|
32
|
+
return parser.content;
|
|
33
|
+
}
|
|
34
|
+
/** Commits `raw()` markup into `part`. */
|
|
35
|
+
function commitRaw(part, html) {
|
|
36
|
+
if (DEV)
|
|
37
|
+
warnRaw();
|
|
38
|
+
report({ html });
|
|
39
|
+
if (part.kind === RAW) {
|
|
40
|
+
const range = part.content;
|
|
41
|
+
if (range.html === html)
|
|
42
|
+
return;
|
|
43
|
+
if (range.end !== range.start)
|
|
44
|
+
removeRange(range.start.nextSibling, range.end);
|
|
45
|
+
const frag = parse(html);
|
|
46
|
+
range.end = frag.lastChild ?? range.start;
|
|
47
|
+
range.html = html;
|
|
48
|
+
range.start.after(frag);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (part.kind !== EMPTY)
|
|
52
|
+
part.clear();
|
|
53
|
+
const start = document.createComment('');
|
|
54
|
+
const frag = parse(html);
|
|
55
|
+
const end = frag.lastChild ?? start;
|
|
56
|
+
frag.prepend(start);
|
|
57
|
+
part.parent().insertBefore(frag, part.end());
|
|
58
|
+
part.kind = RAW;
|
|
59
|
+
part.content = new RawRange(start, end, html);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Trusted markup from your own code (Markdown output, JSON-LD), parsed in a child hole and
|
|
63
|
+
* re-parsed only when the string changes. Never pass user input.
|
|
64
|
+
*/
|
|
65
|
+
export function raw(html) {
|
|
66
|
+
return { [MARKUP]: commitRaw, html };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=raw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw.js","sourceRoot":"","sources":["../../../src/view/render/raw.ts"],"names":[],"mappings":"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","sourcesContent":["// `raw(html)` (view/02-bindings.md \"`raw(html)`\"): trusted markup parsed in a child hole, kept\n// as a node range after a start anchor and re-parsed only when the string changes. Its result\n// carries `commitRaw`, so apps that never call `raw` don't bundle this module.\nimport { DEV } from '#view-dev';\nimport { EMPTY, RAW, type ChildPart } from './child-part.js';\nimport { removeRange } from './nodes.js';\nimport { report } from './seen.js';\nimport { MARKUP, type RawResult } from './values.js';\nimport { warnRaw } from './warn.js';\n\n/** Parsed `raw()` markup: the start anchor, the last node, and the string. */\nexport class RawRange {\n constructor(\n readonly start: Comment,\n public end: Node,\n public html: string,\n ) {}\n\n first(): Node {\n return this.start;\n }\n\n last(): Node {\n return this.end;\n }\n\n remove(): void {\n removeRange(this.start, this.end);\n }\n}\n\nlet parser: HTMLTemplateElement | undefined;\n\n/** `html` parsed by a <template> (its content is reused: read it before the next call). */\nexport function parse(html: string): DocumentFragment {\n parser ??= document.createElement('template');\n parser.innerHTML = html;\n return parser.content;\n}\n\n/** Commits `raw()` markup into `part`. */\nfunction commitRaw(part: ChildPart, html: string): void {\n if (DEV) warnRaw();\n report({ html });\n if (part.kind === RAW) {\n const range = part.content as RawRange;\n if (range.html === html) return;\n if (range.end !== range.start) removeRange(range.start.nextSibling as Node, range.end);\n const frag = parse(html);\n range.end = frag.lastChild ?? range.start;\n range.html = html;\n range.start.after(frag);\n return;\n }\n if (part.kind !== EMPTY) part.clear();\n const start = document.createComment('');\n const frag = parse(html);\n const end = frag.lastChild ?? start;\n frag.prepend(start);\n part.parent().insertBefore(frag, part.end());\n part.kind = RAW;\n part.content = new RawRange(start, end, html);\n}\n\n/**\n * Trusted markup from your own code (Markdown output, JSON-LD), parsed in a child hole and\n * re-parsed only when the string changes. Never pass user input.\n */\nexport function raw(html: string): RawResult {\n return { [MARKUP]: commitRaw, html };\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ChildPart } from './child-part.js';
|
|
2
|
+
import { type SeenMarkup } from './seen.js';
|
|
3
|
+
import type { ChildValue } from './values.js';
|
|
4
|
+
/** Runs `fn` (one scheduler flush) with one shared row-check budget for every render in it. */
|
|
5
|
+
export declare function renderBatch(fn: () => void): void;
|
|
6
|
+
/**
|
|
7
|
+
* Renders `value` into `root`, updating what an earlier call rendered there. `seen` is told
|
|
8
|
+
* about each template the render instantiates (seen.ts).
|
|
9
|
+
*/
|
|
10
|
+
export declare function render(value: ChildValue, root: Element | ShadowRoot | DocumentFragment, seen?: SeenMarkup): void;
|
|
11
|
+
/** Hydration (hydrate.ts): `part`, built over server DOM, is `root`'s part from now on. */
|
|
12
|
+
export declare function setRootPart(root: Node, part: ChildPart): void;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// `render(value, root)`: the client renderer's entry point (view/02-bindings.md "Commit order").
|
|
2
|
+
// The root's child part is cached per root, so later calls update in place. Synchronous: when
|
|
3
|
+
// it returns, the DOM is committed and every element hook's `client` call has run. The
|
|
4
|
+
// scheduler (view/04-scheduler.md) calls it once per dirty host, inside `renderBatch`, so the
|
|
5
|
+
// list dev check's budget (03) is per flush; a call outside a batch gets a budget of its own.
|
|
6
|
+
// `hydrate(value, root)` (hydrate.ts) makes the same root part from server DOM instead (07).
|
|
7
|
+
import { DEV } from '#view-dev';
|
|
8
|
+
import { ChildPart } from './child-part.js';
|
|
9
|
+
import { resetRowChecks } from './dev-check.js';
|
|
10
|
+
import { dropHooks, hookMark, runHooks } from './hooks.js';
|
|
11
|
+
import { listenFor } from './seen.js';
|
|
12
|
+
const roots = new WeakMap();
|
|
13
|
+
let batching = false;
|
|
14
|
+
/** Runs `fn` (one scheduler flush) with one shared row-check budget for every render in it. */
|
|
15
|
+
export function renderBatch(fn) {
|
|
16
|
+
if (!DEV) {
|
|
17
|
+
fn(); // the budget is a development check: production needs no batch state
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
resetRowChecks();
|
|
21
|
+
const outer = batching;
|
|
22
|
+
batching = true;
|
|
23
|
+
try {
|
|
24
|
+
fn();
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
batching = outer;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Renders `value` into `root`, updating what an earlier call rendered there. `seen` is told
|
|
32
|
+
* about each template the render instantiates (seen.ts).
|
|
33
|
+
*/
|
|
34
|
+
export function render(value, root, seen) {
|
|
35
|
+
let part = roots.get(root);
|
|
36
|
+
if (part === undefined) {
|
|
37
|
+
part = new ChildPart(root, null, null, 0, false, 0);
|
|
38
|
+
roots.set(root, part);
|
|
39
|
+
}
|
|
40
|
+
const mark = hookMark();
|
|
41
|
+
if (DEV && !batching)
|
|
42
|
+
resetRowChecks();
|
|
43
|
+
const outer = listenFor(seen);
|
|
44
|
+
try {
|
|
45
|
+
part.commit(value);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
dropHooks(mark);
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
listenFor(outer);
|
|
53
|
+
}
|
|
54
|
+
runHooks(mark);
|
|
55
|
+
}
|
|
56
|
+
/** Hydration (hydrate.ts): `part`, built over server DOM, is `root`'s part from now on. */
|
|
57
|
+
export function setRootPart(root, part) {
|
|
58
|
+
roots.set(root, part);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/view/render/render.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,8FAA8F;AAC9F,uFAAuF;AACvF,8FAA8F;AAC9F,8FAA8F;AAC9F,6FAA6F;AAC7F,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAmB,MAAM,WAAW,CAAC;AAGvD,MAAM,KAAK,GAAG,IAAI,OAAO,EAAmB,CAAC;AAC7C,IAAI,QAAQ,GAAG,KAAK,CAAC;AAErB,+FAA+F;AAC/F,MAAM,UAAU,WAAW,CAAC,EAAc;IACxC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,EAAE,EAAE,CAAC,CAAC,qEAAqE;QAC3E,OAAO;IACT,CAAC;IACD,cAAc,EAAE,CAAC;IACjB,MAAM,KAAK,GAAG,QAAQ,CAAC;IACvB,QAAQ,GAAG,IAAI,CAAC;IAChB,IAAI,CAAC;QACH,EAAE,EAAE,CAAC;IACP,CAAC;YAAS,CAAC;QACT,QAAQ,GAAG,KAAK,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM,CACpB,KAAiB,EACjB,IAA6C,EAC7C,IAAiB;IAEjB,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QACpD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,IAAI,GAAG,IAAI,CAAC,QAAQ;QAAE,cAAc,EAAE,CAAC;IACvC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,WAAW,CAAC,IAAU,EAAE,IAAe;IACrD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACxB,CAAC","sourcesContent":["// `render(value, root)`: the client renderer's entry point (view/02-bindings.md \"Commit order\").\n// The root's child part is cached per root, so later calls update in place. Synchronous: when\n// it returns, the DOM is committed and every element hook's `client` call has run. The\n// scheduler (view/04-scheduler.md) calls it once per dirty host, inside `renderBatch`, so the\n// list dev check's budget (03) is per flush; a call outside a batch gets a budget of its own.\n// `hydrate(value, root)` (hydrate.ts) makes the same root part from server DOM instead (07).\nimport { DEV } from '#view-dev';\nimport { ChildPart } from './child-part.js';\nimport { resetRowChecks } from './dev-check.js';\nimport { dropHooks, hookMark, runHooks } from './hooks.js';\nimport { listenFor, type SeenMarkup } from './seen.js';\nimport type { ChildValue } from './values.js';\n\nconst roots = new WeakMap<Node, ChildPart>();\nlet batching = false;\n\n/** Runs `fn` (one scheduler flush) with one shared row-check budget for every render in it. */\nexport function renderBatch(fn: () => void): void {\n if (!DEV) {\n fn(); // the budget is a development check: production needs no batch state\n return;\n }\n resetRowChecks();\n const outer = batching;\n batching = true;\n try {\n fn();\n } finally {\n batching = outer;\n }\n}\n\n/**\n * Renders `value` into `root`, updating what an earlier call rendered there. `seen` is told\n * about each template the render instantiates (seen.ts).\n */\nexport function render(\n value: ChildValue,\n root: Element | ShadowRoot | DocumentFragment,\n seen?: SeenMarkup,\n): void {\n let part = roots.get(root);\n if (part === undefined) {\n part = new ChildPart(root, null, null, 0, false, 0);\n roots.set(root, part);\n }\n const mark = hookMark();\n if (DEV && !batching) resetRowChecks();\n const outer = listenFor(seen);\n try {\n part.commit(value);\n } catch (error) {\n dropHooks(mark);\n throw error;\n } finally {\n listenFor(outer);\n }\n runHooks(mark);\n}\n\n/** Hydration (hydrate.ts): `part`, built over server DOM, is `root`'s part from now on. */\nexport function setRootPart(root: Node, part: ChildPart): void {\n roots.set(root, part);\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ChildPart } from './child-part.js';
|
|
2
|
+
import { type List } from './rows.js';
|
|
3
|
+
import type { ListResult } from './values.js';
|
|
4
|
+
export declare function reorder(part: ChildPart, list: List, l: ListResult, rows: ChildPart[], s: number, oe: number, ne: number): void;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { clearList, createRows } from './list.js';
|
|
2
|
+
import { lis, placeRows } from './place.js';
|
|
3
|
+
import { firstFrom, newRow, updateRow } from './rows.js';
|
|
4
|
+
function match(old, keys, s, oe, ne) {
|
|
5
|
+
const src = new Int32Array(ne - s + 1).fill(-1);
|
|
6
|
+
const keep = new Uint8Array(ne - s + 1);
|
|
7
|
+
const m = { src, keep, found: 0 };
|
|
8
|
+
let os = s;
|
|
9
|
+
let ns = s;
|
|
10
|
+
for (; os <= oe && ns <= ne; m.found++) {
|
|
11
|
+
const head = old[os].key;
|
|
12
|
+
const tail = old[oe].key;
|
|
13
|
+
if (keys[ns - s] === head) {
|
|
14
|
+
keep[ns - s] = 1;
|
|
15
|
+
src[ns++ - s] = os++;
|
|
16
|
+
}
|
|
17
|
+
else if (keys[ne - s] === tail) {
|
|
18
|
+
keep[ne - s] = 1;
|
|
19
|
+
src[ne-- - s] = oe--;
|
|
20
|
+
}
|
|
21
|
+
else if (keys[ne - s] === head)
|
|
22
|
+
src[ne-- - s] = os++;
|
|
23
|
+
else if (keys[ns - s] === tail)
|
|
24
|
+
src[ns++ - s] = oe--;
|
|
25
|
+
else
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
if (os > oe || ns > ne)
|
|
29
|
+
return m;
|
|
30
|
+
m.keep = undefined;
|
|
31
|
+
const byKey = new Map();
|
|
32
|
+
for (let j = os; j <= oe; j++)
|
|
33
|
+
byKey.set(old[j].key, j);
|
|
34
|
+
for (let i = ns; i <= ne; i++) {
|
|
35
|
+
const key = keys[i - s];
|
|
36
|
+
const j = byKey.get(key);
|
|
37
|
+
if (j === undefined)
|
|
38
|
+
continue; // a new key (or, in production, a later duplicate)
|
|
39
|
+
byKey.delete(key);
|
|
40
|
+
src[i - s] = j;
|
|
41
|
+
m.found++;
|
|
42
|
+
}
|
|
43
|
+
return m;
|
|
44
|
+
}
|
|
45
|
+
export function reorder(part, list, l, rows, s, oe, ne) {
|
|
46
|
+
const { items, key } = l;
|
|
47
|
+
const old = list.rows;
|
|
48
|
+
const keys = [];
|
|
49
|
+
for (let i = s; i <= ne; i++)
|
|
50
|
+
keys.push(key(items[i]));
|
|
51
|
+
const m = match(old, keys, s, oe, ne);
|
|
52
|
+
const end = firstFrom(old, oe + 1, part);
|
|
53
|
+
if (m.found === 0) {
|
|
54
|
+
// Nothing reused: drop the old rows (all at once when they are the whole list).
|
|
55
|
+
if (s === 0 && oe === old.length - 1)
|
|
56
|
+
clearList(part, list);
|
|
57
|
+
else
|
|
58
|
+
for (let j = s; j <= oe; j++)
|
|
59
|
+
old[j].clear();
|
|
60
|
+
createRows(part, list, l, rows, s, ne, end, keys);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const src = m.src;
|
|
64
|
+
const reused = new Uint8Array(oe - s + 1);
|
|
65
|
+
let frag = null;
|
|
66
|
+
let moved = false;
|
|
67
|
+
let last = -1;
|
|
68
|
+
for (let i = s; i <= ne; i++) {
|
|
69
|
+
const j = src[i - s];
|
|
70
|
+
if (j < 0) {
|
|
71
|
+
frag ??= document.createDocumentFragment();
|
|
72
|
+
rows.push(newRow(null, frag, l, items[i], keys[i - s], i));
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
reused[j - s] = 1;
|
|
76
|
+
if (j < last)
|
|
77
|
+
moved = true;
|
|
78
|
+
else
|
|
79
|
+
last = j;
|
|
80
|
+
const row = old[j];
|
|
81
|
+
updateRow(row, items[i], l);
|
|
82
|
+
rows.push(row);
|
|
83
|
+
}
|
|
84
|
+
for (let j = s; j <= oe; j++)
|
|
85
|
+
if (reused[j - s] === 0)
|
|
86
|
+
old[j].clear();
|
|
87
|
+
if (!moved && frag === null)
|
|
88
|
+
return;
|
|
89
|
+
const keep = moved ? (m.keep ?? lis(src)) : undefined;
|
|
90
|
+
placeRows(part.parent(), rows, s, ne, src, keep, end);
|
|
91
|
+
if (frag === null)
|
|
92
|
+
return;
|
|
93
|
+
for (let i = s; i <= ne; i++) {
|
|
94
|
+
if (src[i - s] >= 0)
|
|
95
|
+
continue;
|
|
96
|
+
const row = rows[i];
|
|
97
|
+
row.parentNode = null;
|
|
98
|
+
row.owner = list;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=reorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reorder.js","sourceRoot":"","sources":["../../../src/view/render/reorder.ts"],"names":[],"mappings":"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","sourcesContent":["// Reordering the middle of a list (view/03-lists.md \"Reconciliation\", steps 1–3): old rows\n// `s…oe` become new rows `s…ne` once the common prefix and suffix are trimmed. Keys are matched\n// by a two-ended scan first (head and tail, crossed both ways), so swaps, single moves and\n// reversals need no map: the rows matched in place stay and the crossed ones move. When the\n// scan gets stuck, a key map matches the rest and the rows on a longest increasing subsequence\n// of old positions stay. Reused rows re-render in document order before anything moves; gone\n// rows are removed. The benchmark behind this choice is recorded in the spec.\nimport type { ChildPart } from './child-part.js';\nimport { clearList, createRows } from './list.js';\nimport { lis, placeRows } from './place.js';\nimport { firstFrom, newRow, updateRow, type List } from './rows.js';\nimport type { ListResult } from './values.js';\n\n/** The matching: old positions per new row (-1: new), what stays, and how many were found. */\ninterface Match {\n readonly src: Int32Array;\n /** Rows to keep in place; undefined: compute from `src` (the key map was needed). */\n keep: Uint8Array | undefined;\n found: number;\n}\n\nfunction match(\n old: readonly ChildPart[],\n keys: readonly unknown[],\n s: number,\n oe: number,\n ne: number,\n): Match {\n const src = new Int32Array(ne - s + 1).fill(-1);\n const keep = new Uint8Array(ne - s + 1);\n const m: Match = { src, keep, found: 0 };\n let os = s;\n let ns = s;\n for (; os <= oe && ns <= ne; m.found++) {\n const head = (old[os] as ChildPart).key;\n const tail = (old[oe] as ChildPart).key;\n if (keys[ns - s] === head) {\n keep[ns - s] = 1;\n src[ns++ - s] = os++;\n } else if (keys[ne - s] === tail) {\n keep[ne - s] = 1;\n src[ne-- - s] = oe--;\n } else if (keys[ne - s] === head) src[ne-- - s] = os++;\n else if (keys[ns - s] === tail) src[ns++ - s] = oe--;\n else break;\n }\n if (os > oe || ns > ne) return m;\n m.keep = undefined;\n const byKey = new Map<unknown, number>();\n for (let j = os; j <= oe; j++) byKey.set((old[j] as ChildPart).key, j);\n for (let i = ns; i <= ne; i++) {\n const key = keys[i - s];\n const j = byKey.get(key);\n if (j === undefined) continue; // a new key (or, in production, a later duplicate)\n byKey.delete(key);\n src[i - s] = j;\n m.found++;\n }\n return m;\n}\n\nexport function reorder(\n part: ChildPart,\n list: List,\n l: ListResult,\n rows: ChildPart[],\n s: number,\n oe: number,\n ne: number,\n): void {\n const { items, key } = l;\n const old = list.rows;\n const keys: unknown[] = [];\n for (let i = s; i <= ne; i++) keys.push(key(items[i]));\n const m = match(old, keys, s, oe, ne);\n const end = firstFrom(old, oe + 1, part);\n if (m.found === 0) {\n // Nothing reused: drop the old rows (all at once when they are the whole list).\n if (s === 0 && oe === old.length - 1) clearList(part, list);\n else for (let j = s; j <= oe; j++) (old[j] as ChildPart).clear();\n createRows(part, list, l, rows, s, ne, end, keys);\n return;\n }\n const src = m.src;\n const reused = new Uint8Array(oe - s + 1);\n let frag: DocumentFragment | null = null;\n let moved = false;\n let last = -1;\n for (let i = s; i <= ne; i++) {\n const j = src[i - s] as number;\n if (j < 0) {\n frag ??= document.createDocumentFragment();\n rows.push(newRow(null, frag, l, items[i], keys[i - s], i));\n continue;\n }\n reused[j - s] = 1;\n if (j < last) moved = true;\n else last = j;\n const row = old[j] as ChildPart;\n updateRow(row, items[i], l);\n rows.push(row);\n }\n for (let j = s; j <= oe; j++) if (reused[j - s] === 0) (old[j] as ChildPart).clear();\n if (!moved && frag === null) return;\n const keep = moved ? (m.keep ?? lis(src)) : undefined;\n placeRows(part.parent(), rows, s, ne, src, keep, end);\n if (frag === null) return;\n for (let i = s; i <= ne; i++) {\n if ((src[i - s] as number) >= 0) continue;\n const row = rows[i] as ChildPart;\n row.parentNode = null;\n row.owner = list;\n }\n}\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ChildPart, type Owner } from './child-part.js';
|
|
2
|
+
import type { ListResult } from './values.js';
|
|
3
|
+
/** The rows of a list or the items of an array, owned by one child part. */
|
|
4
|
+
export declare class List implements Owner {
|
|
5
|
+
readonly part: ChildPart;
|
|
6
|
+
rows: ChildPart[];
|
|
7
|
+
/** While rows are created into a fragment: they append to it. */
|
|
8
|
+
building: DocumentFragment | null;
|
|
9
|
+
/** Where the development re-evaluation check continues (dev-check.ts). */
|
|
10
|
+
cursor: number;
|
|
11
|
+
constructor(part: ChildPart);
|
|
12
|
+
parentFor(): Node;
|
|
13
|
+
endFor(index: number): Node | null;
|
|
14
|
+
first(): Node | null;
|
|
15
|
+
last(): Node | null;
|
|
16
|
+
}
|
|
17
|
+
/** The first node of `rows[from…]`, or the end of the list's part. */
|
|
18
|
+
export declare function firstFrom(rows: readonly ChildPart[], from: number, part: ChildPart): Node | null;
|
|
19
|
+
/** `Object.is`, or for arrays and plain objects the same entries by `Object.is` (one level). */
|
|
20
|
+
export declare function samePick(a: unknown, b: unknown): boolean;
|
|
21
|
+
export declare function updateRow(row: ChildPart, item: unknown, l: ListResult): void;
|
|
22
|
+
/** A new row: open (positioned by `owner`), or appended to `parent` until placed. */
|
|
23
|
+
export declare function newRow(owner: List | null, parent: Node | null, l: ListResult, item: unknown, key: unknown, index: number): ChildPart;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Rows of lists and arrays (view/03-lists.md "Row skipping", "Row boundaries"): the list that
|
|
2
|
+
// owns them (and resolves their positions), row skipping by item identity and a shallow pick
|
|
3
|
+
// comparison, and row creation. Shared by list.ts and the reordering step (reorder.ts).
|
|
4
|
+
import { ChildPart } from './child-part.js';
|
|
5
|
+
/** The rows of a list or the items of an array, owned by one child part. */
|
|
6
|
+
export class List {
|
|
7
|
+
constructor(part) {
|
|
8
|
+
this.part = part;
|
|
9
|
+
this.rows = [];
|
|
10
|
+
this.building = null;
|
|
11
|
+
this.cursor = 0;
|
|
12
|
+
}
|
|
13
|
+
parentFor() {
|
|
14
|
+
return this.building ?? this.part.parent();
|
|
15
|
+
}
|
|
16
|
+
endFor(index) {
|
|
17
|
+
return this.building !== null ? null : firstFrom(this.rows, index + 1, this.part);
|
|
18
|
+
}
|
|
19
|
+
first() {
|
|
20
|
+
const rows = this.rows;
|
|
21
|
+
for (let i = 0; i < rows.length; i++) {
|
|
22
|
+
const node = rows[i].first();
|
|
23
|
+
if (node !== null)
|
|
24
|
+
return node;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
last() {
|
|
29
|
+
const rows = this.rows;
|
|
30
|
+
for (let i = rows.length - 1; i >= 0; i--) {
|
|
31
|
+
const node = rows[i].last();
|
|
32
|
+
if (node !== null)
|
|
33
|
+
return node;
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** The first node of `rows[from…]`, or the end of the list's part. */
|
|
39
|
+
export function firstFrom(rows, from, part) {
|
|
40
|
+
for (let j = from; j < rows.length; j++) {
|
|
41
|
+
const node = rows[j].first();
|
|
42
|
+
if (node !== null)
|
|
43
|
+
return node;
|
|
44
|
+
}
|
|
45
|
+
return part.end();
|
|
46
|
+
}
|
|
47
|
+
/** `Object.is`, or for arrays and plain objects the same entries by `Object.is` (one level). */
|
|
48
|
+
export function samePick(a, b) {
|
|
49
|
+
if (Object.is(a, b))
|
|
50
|
+
return true;
|
|
51
|
+
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
|
|
52
|
+
return false;
|
|
53
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
54
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
|
|
55
|
+
return false;
|
|
56
|
+
for (let i = 0; i < a.length; i++)
|
|
57
|
+
if (!Object.is(a[i], b[i]))
|
|
58
|
+
return false;
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
const proto = Object.getPrototypeOf(a);
|
|
62
|
+
if ((proto !== Object.prototype && proto !== null) || Object.getPrototypeOf(b) !== proto) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const keys = Object.keys(a);
|
|
66
|
+
if (keys.length !== Object.keys(b).length)
|
|
67
|
+
return false;
|
|
68
|
+
for (const k of keys) {
|
|
69
|
+
if (!Object.hasOwn(b, k))
|
|
70
|
+
return false;
|
|
71
|
+
if (!Object.is(a[k], b[k])) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
export function updateRow(row, item, l) {
|
|
78
|
+
const picked = l.pick === undefined ? undefined : l.pick(item);
|
|
79
|
+
if (item === row.item && samePick(picked, row.picked))
|
|
80
|
+
return;
|
|
81
|
+
row.item = item;
|
|
82
|
+
row.picked = picked;
|
|
83
|
+
row.commit(l.row(item, picked));
|
|
84
|
+
}
|
|
85
|
+
/** A new row: open (positioned by `owner`), or appended to `parent` until placed. */
|
|
86
|
+
export function newRow(owner, parent, l, item, key, index) {
|
|
87
|
+
const row = new ChildPart(parent, null, owner, index, false, -1);
|
|
88
|
+
const picked = l.pick === undefined ? undefined : l.pick(item);
|
|
89
|
+
row.key = key;
|
|
90
|
+
row.item = item;
|
|
91
|
+
row.picked = picked;
|
|
92
|
+
row.commit(l.row(item, picked));
|
|
93
|
+
return row;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=rows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rows.js","sourceRoot":"","sources":["../../../src/view/render/rows.ts"],"names":[],"mappings":"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","sourcesContent":["// Rows of lists and arrays (view/03-lists.md \"Row skipping\", \"Row boundaries\"): the list that\n// owns them (and resolves their positions), row skipping by item identity and a shallow pick\n// comparison, and row creation. Shared by list.ts and the reordering step (reorder.ts).\nimport { ChildPart, type Owner } from './child-part.js';\nimport type { ListResult } from './values.js';\n\n/** The rows of a list or the items of an array, owned by one child part. */\nexport class List implements Owner {\n readonly part: ChildPart;\n rows: ChildPart[];\n /** While rows are created into a fragment: they append to it. */\n building: DocumentFragment | null;\n /** Where the development re-evaluation check continues (dev-check.ts). */\n cursor: number;\n\n constructor(part: ChildPart) {\n this.part = part;\n this.rows = [];\n this.building = null;\n this.cursor = 0;\n }\n\n parentFor(): Node {\n return this.building ?? this.part.parent();\n }\n\n endFor(index: number): Node | null {\n return this.building !== null ? null : firstFrom(this.rows, index + 1, this.part);\n }\n\n first(): Node | null {\n const rows = this.rows;\n for (let i = 0; i < rows.length; i++) {\n const node = (rows[i] as ChildPart).first();\n if (node !== null) return node;\n }\n return null;\n }\n\n last(): Node | null {\n const rows = this.rows;\n for (let i = rows.length - 1; i >= 0; i--) {\n const node = (rows[i] as ChildPart).last();\n if (node !== null) return node;\n }\n return null;\n }\n}\n\n/** The first node of `rows[from…]`, or the end of the list's part. */\nexport function firstFrom(rows: readonly ChildPart[], from: number, part: ChildPart): Node | null {\n for (let j = from; j < rows.length; j++) {\n const node = (rows[j] as ChildPart).first();\n if (node !== null) return node;\n }\n return part.end();\n}\n\n/** `Object.is`, or for arrays and plain objects the same entries by `Object.is` (one level). */\nexport function samePick(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false;\n return true;\n }\n const proto = Object.getPrototypeOf(a) as unknown;\n if ((proto !== Object.prototype && proto !== null) || Object.getPrototypeOf(b) !== proto) {\n return false;\n }\n const keys = Object.keys(a);\n if (keys.length !== Object.keys(b).length) return false;\n for (const k of keys) {\n if (!Object.hasOwn(b, k)) return false;\n if (!Object.is((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k])) {\n return false;\n }\n }\n return true;\n}\n\nexport function updateRow(row: ChildPart, item: unknown, l: ListResult): void {\n const picked = l.pick === undefined ? undefined : l.pick(item);\n if (item === row.item && samePick(picked, row.picked)) return;\n row.item = item;\n row.picked = picked;\n row.commit(l.row(item, picked));\n}\n\n/** A new row: open (positioned by `owner`), or appended to `parent` until placed. */\nexport function newRow(\n owner: List | null,\n parent: Node | null,\n l: ListResult,\n item: unknown,\n key: unknown,\n index: number,\n): ChildPart {\n const row = new ChildPart(parent, null, owner, index, false, -1);\n const picked = l.pick === undefined ? undefined : l.pick(item);\n row.key = key;\n row.item = item;\n row.picked = picked;\n row.commit(l.row(item, picked));\n return row;\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PartSpec } from '../normalize/types.js';
|
|
2
|
+
/** What is reported: a template object, or `raw()` markup as `{ html }`. */
|
|
3
|
+
export interface Markup {
|
|
4
|
+
readonly html: string;
|
|
5
|
+
readonly parts?: readonly PartSpec[];
|
|
6
|
+
}
|
|
7
|
+
export type SeenMarkup = (markup: Markup) => void;
|
|
8
|
+
/** Reports `markup` to the current render's listener, if any. */
|
|
9
|
+
export declare function report(markup: Markup): void;
|
|
10
|
+
/** Sets the listener for one render; returns the previous one, to restore afterwards. */
|
|
11
|
+
export declare function listenFor(fn: SeenMarkup | undefined): SeenMarkup | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
let seen;
|
|
2
|
+
let last;
|
|
3
|
+
/** Reports `markup` to the current render's listener, if any. */
|
|
4
|
+
export function report(markup) {
|
|
5
|
+
if (seen !== undefined && markup !== last) {
|
|
6
|
+
last = markup;
|
|
7
|
+
seen(markup);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Sets the listener for one render; returns the previous one, to restore afterwards. */
|
|
11
|
+
export function listenFor(fn) {
|
|
12
|
+
const outer = seen;
|
|
13
|
+
seen = fn;
|
|
14
|
+
last = undefined;
|
|
15
|
+
return outer;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=seen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seen.js","sourceRoot":"","sources":["../../../src/view/render/seen.ts"],"names":[],"mappings":"AAcA,IAAI,IAA4B,CAAC;AACjC,IAAI,IAAwB,CAAC;AAE7B,iEAAiE;AACjE,MAAM,UAAU,MAAM,CAAC,MAAc;IACnC,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAC1C,IAAI,GAAG,MAAM,CAAC;QACd,IAAI,CAAC,MAAM,CAAC,CAAC;IACf,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,SAAS,CAAC,EAA0B;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC;IACnB,IAAI,GAAG,EAAE,CAAC;IACV,IAAI,GAAG,SAAS,CAAC;IACjB,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["// The templates a render instantiates, reported to the caller of `render`/`hydrate` (view/02\n// \"Commit order\"). Core uses it to listen only for the intent events a component's markup names\n// (view/05-element.md \"Intent events\"). Reporting costs one comparison per instance when no\n// one listens, and one call per run of instances of the same template when someone does.\nimport type { PartSpec } from '../normalize/types.js';\n\n/** What is reported: a template object, or `raw()` markup as `{ html }`. */\nexport interface Markup {\n readonly html: string;\n readonly parts?: readonly PartSpec[];\n}\n\nexport type SeenMarkup = (markup: Markup) => void;\n\nlet seen: SeenMarkup | undefined;\nlet last: Markup | undefined;\n\n/** Reports `markup` to the current render's listener, if any. */\nexport function report(markup: Markup): void {\n if (seen !== undefined && markup !== last) {\n last = markup;\n seen(markup);\n }\n}\n\n/** Sets the listener for one render; returns the previous one, to restore afterwards. */\nexport function listenFor(fn: SeenMarkup | undefined): SeenMarkup | undefined {\n const outer = seen;\n seen = fn;\n last = undefined;\n return outer;\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TemplateResult } from '../template.js';
|
|
2
|
+
import type { ChildPart } from './child-part.js';
|
|
3
|
+
/** Renders nothing in a child hole; removes the attribute in an attribute hole. */
|
|
4
|
+
export declare const nothing: unique symbol;
|
|
5
|
+
/** Internal: "never committed", so a part's first commit always writes. */
|
|
6
|
+
export declare const UNSET: unique symbol;
|
|
7
|
+
/** Internal: the key of `raw`'s result; its value is the function that commits the markup. */
|
|
8
|
+
export declare const MARKUP: unique symbol;
|
|
9
|
+
/** Internal: the key of `each`'s result; its value is the function that commits the list. */
|
|
10
|
+
export declare const EACH: unique symbol;
|
|
11
|
+
/** Trusted markup for a child hole: what `raw(html)` returns. */
|
|
12
|
+
export interface RawResult {
|
|
13
|
+
readonly [MARKUP]: (part: ChildPart, html: string) => void;
|
|
14
|
+
readonly html: string;
|
|
15
|
+
}
|
|
16
|
+
/** A keyed list for a child hole: what `each(…)` returns. */
|
|
17
|
+
export interface ListResult {
|
|
18
|
+
readonly [EACH]: (part: ChildPart, list: ListResult) => void;
|
|
19
|
+
readonly items: readonly unknown[];
|
|
20
|
+
readonly key: (item: unknown) => unknown;
|
|
21
|
+
readonly row: (item: unknown, picked: unknown) => unknown;
|
|
22
|
+
readonly pick: ((item: unknown) => unknown) | undefined;
|
|
23
|
+
}
|
|
24
|
+
/** Everything a child hole accepts (view/02-bindings.md "Child values"). */
|
|
25
|
+
export type ChildValue = string | number | boolean | null | undefined | typeof nothing | TemplateResult | ListResult | RawResult | readonly ChildValue[];
|
|
26
|
+
export declare const isRaw: (value: object) => value is RawResult;
|
|
27
|
+
/** The markup of a `raw()` value, or undefined for anything else. */
|
|
28
|
+
export declare const rawHtml: (value: object) => string | undefined;
|
|
29
|
+
export declare const isList: (value: object) => value is ListResult;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Renders nothing in a child hole; removes the attribute in an attribute hole. */
|
|
2
|
+
export const nothing = Symbol('gyral.nothing');
|
|
3
|
+
/** Internal: "never committed", so a part's first commit always writes. */
|
|
4
|
+
export const UNSET = Symbol('gyral.unset');
|
|
5
|
+
/** Internal: the key of `raw`'s result; its value is the function that commits the markup. */
|
|
6
|
+
export const MARKUP = Symbol('gyral.raw');
|
|
7
|
+
/** Internal: the key of `each`'s result; its value is the function that commits the list. */
|
|
8
|
+
export const EACH = Symbol('gyral.each');
|
|
9
|
+
export const isRaw = (value) => MARKUP in value;
|
|
10
|
+
/** The markup of a `raw()` value, or undefined for anything else. */
|
|
11
|
+
export const rawHtml = (value) => isRaw(value) ? value.html : undefined;
|
|
12
|
+
export const isList = (value) => EACH in value;
|
|
13
|
+
//# sourceMappingURL=values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.js","sourceRoot":"","sources":["../../../src/view/render/values.ts"],"names":[],"mappings":"AAQA,mFAAmF;AACnF,MAAM,CAAC,MAAM,OAAO,GAAkB,MAAM,CAAC,eAAe,CAAC,CAAC;AAE9D,2EAA2E;AAC3E,MAAM,CAAC,MAAM,KAAK,GAAkB,MAAM,CAAC,aAAa,CAAC,CAAC;AAE1D,8FAA8F;AAC9F,MAAM,CAAC,MAAM,MAAM,GAAkB,MAAM,CAAC,WAAW,CAAC,CAAC;AACzD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,IAAI,GAAkB,MAAM,CAAC,YAAY,CAAC,CAAC;AA8BxD,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAsB,EAAE,CAAC,MAAM,IAAI,KAAK,CAAC;AAE5E,qEAAqE;AACrE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAa,EAAsB,EAAE,CAC3D,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAExC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAa,EAAuB,EAAE,CAAC,IAAI,IAAI,KAAK,CAAC","sourcesContent":["// Child values besides text and templates (view/02-bindings.md \"Child values\", \"`raw(html)`\",\n// \"`nothing`\") and the result of `each` (view/03-lists.md \"The API\"). Each is recognised by a\n// symbol, so data parsed from JSON can never pass for one. `each` lives in list.ts and `raw` in\n// raw.ts: their results carry the code that commits them, so an app that never calls one\n// doesn't bundle that code.\nimport type { TemplateResult } from '../template.js';\nimport type { ChildPart } from './child-part.js';\n\n/** Renders nothing in a child hole; removes the attribute in an attribute hole. */\nexport const nothing: unique symbol = Symbol('gyral.nothing');\n\n/** Internal: \"never committed\", so a part's first commit always writes. */\nexport const UNSET: unique symbol = Symbol('gyral.unset');\n\n/** Internal: the key of `raw`'s result; its value is the function that commits the markup. */\nexport const MARKUP: unique symbol = Symbol('gyral.raw');\n/** Internal: the key of `each`'s result; its value is the function that commits the list. */\nexport const EACH: unique symbol = Symbol('gyral.each');\n\n/** Trusted markup for a child hole: what `raw(html)` returns. */\nexport interface RawResult {\n readonly [MARKUP]: (part: ChildPart, html: string) => void;\n readonly html: string;\n}\n\n/** A keyed list for a child hole: what `each(…)` returns. */\nexport interface ListResult {\n readonly [EACH]: (part: ChildPart, list: ListResult) => void;\n readonly items: readonly unknown[];\n readonly key: (item: unknown) => unknown;\n readonly row: (item: unknown, picked: unknown) => unknown;\n readonly pick: ((item: unknown) => unknown) | undefined;\n}\n\n/** Everything a child hole accepts (view/02-bindings.md \"Child values\"). */\nexport type ChildValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | typeof nothing\n | TemplateResult\n | ListResult\n | RawResult\n | readonly ChildValue[];\n\nexport const isRaw = (value: object): value is RawResult => MARKUP in value;\n\n/** The markup of a `raw()` value, or undefined for anything else. */\nexport const rawHtml = (value: object): string | undefined =>\n isRaw(value) ? value.html : undefined;\n\nexport const isList = (value: object): value is ListResult => EACH in value;\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A child hole got a value it can't render: an error in development. */
|
|
2
|
+
export declare function badChild(value: unknown): never;
|
|
3
|
+
/** `true` in a child hole, once per part: usually a `cond && x` slip. */
|
|
4
|
+
export declare function warnTrue(part: object): void;
|
|
5
|
+
/** An attribute or text-content hole got an object or function, once per part. */
|
|
6
|
+
export declare function warnValue(part: object, value: unknown, where: string): void;
|
|
7
|
+
/** `raw()` parsed in the browser, once per page. */
|
|
8
|
+
export declare function warnRaw(): void;
|
|
9
|
+
/** Keys must be unique strings or numbers: an error in development. */
|
|
10
|
+
export declare function badKey(key: unknown, index: number, duplicate: boolean): never;
|
|
11
|
+
/** A skipped row would render differently: it reads something besides `item` and `pick`. */
|
|
12
|
+
export declare function warnImpureRow(row: (...args: never[]) => unknown): void;
|
|
13
|
+
/** A hook hole got something other than a hook result. */
|
|
14
|
+
export declare function badHook(value: unknown): never;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// Development-only errors and warnings of the renderer (view/02-bindings.md "Child values",
|
|
2
|
+
// view/03-lists.md "Keys", view/09-template-rules.md "Warnings"). Every call site is guarded by
|
|
3
|
+
// `if (DEV)`, so production bundles drop this module. Messages say what to write instead.
|
|
4
|
+
const SPEC = 'docs/design-docs/view';
|
|
5
|
+
const warned = new WeakSet();
|
|
6
|
+
const describe = (value) => typeof value === 'function'
|
|
7
|
+
? 'a function'
|
|
8
|
+
: Array.isArray(value)
|
|
9
|
+
? 'an array'
|
|
10
|
+
: typeof value === 'object'
|
|
11
|
+
? `an object (${Object.prototype.toString.call(value).slice(8, -1)})`
|
|
12
|
+
: `a ${typeof value}`;
|
|
13
|
+
/** A child hole got a value it can't render: an error in development. */
|
|
14
|
+
export function badChild(value) {
|
|
15
|
+
throw new TypeError(`gyral: a child hole got ${describe(value)}, which it can't render. Child holes take ` +
|
|
16
|
+
`text, numbers, html\`…\` results, each(…), arrays, raw(…), or null/undefined/false/` +
|
|
17
|
+
`nothing for nothing. Format the value as text, or render it with a template ` +
|
|
18
|
+
`(${SPEC}/02-bindings.md "Child values").`);
|
|
19
|
+
}
|
|
20
|
+
/** `true` in a child hole, once per part: usually a `cond && x` slip. */
|
|
21
|
+
export function warnTrue(part) {
|
|
22
|
+
if (warned.has(part))
|
|
23
|
+
return;
|
|
24
|
+
warned.add(part);
|
|
25
|
+
console.warn('gyral: `true` in a child hole renders nothing. It is usually a `cond && x` slip where ' +
|
|
26
|
+
'cond is a boolean and x is missing; write `cond ? x : nothing` ' +
|
|
27
|
+
`(${SPEC}/02-bindings.md "Child values").`);
|
|
28
|
+
}
|
|
29
|
+
/** An attribute or text-content hole got an object or function, once per part. */
|
|
30
|
+
export function warnValue(part, value, where) {
|
|
31
|
+
if (warned.has(part))
|
|
32
|
+
return;
|
|
33
|
+
warned.add(part);
|
|
34
|
+
console.warn(`gyral: ${where} got ${describe(value)}; it is written as String(value). Pass a string, ` +
|
|
35
|
+
`number or boolean, or null/undefined/nothing to leave it out ` +
|
|
36
|
+
`(${SPEC}/02-bindings.md "Attribute values").`);
|
|
37
|
+
}
|
|
38
|
+
let rawWarned = false;
|
|
39
|
+
/** `raw()` parsed in the browser, once per page. */
|
|
40
|
+
export function warnRaw() {
|
|
41
|
+
if (rawWarned)
|
|
42
|
+
return;
|
|
43
|
+
rawWarned = true;
|
|
44
|
+
console.warn('gyral: raw() rendered in the browser. It works, but every change re-parses the markup; ' +
|
|
45
|
+
'prefer templates for content that changes, and keep raw() for server-rendered markup ' +
|
|
46
|
+
`(${SPEC}/09-template-rules.md "Warnings").`);
|
|
47
|
+
}
|
|
48
|
+
/** Keys must be unique strings or numbers: an error in development. */
|
|
49
|
+
export function badKey(key, index, duplicate) {
|
|
50
|
+
const problem = duplicate
|
|
51
|
+
? `the key ${JSON.stringify(key)} appears twice (again at index ${String(index)})`
|
|
52
|
+
: `the key at index ${String(index)} is ${describe(key)}`;
|
|
53
|
+
throw new Error(`gyral: each(): ${problem}. Keys must be unique strings or numbers within a list, such ` +
|
|
54
|
+
`as a stable id: each(items, (x) => x.id, Row) (${SPEC}/03-lists.md "Keys").`);
|
|
55
|
+
}
|
|
56
|
+
/** A skipped row would render differently: it reads something besides `item` and `pick`. */
|
|
57
|
+
export function warnImpureRow(row) {
|
|
58
|
+
const name = row.name === '' ? 'a row function' : `the row function ${row.name}`;
|
|
59
|
+
console.warn(`gyral: each(): ${name} depends on something not passed through \`item\` or \`pick\`, so ` +
|
|
60
|
+
'skipped rows would show stale content. Return what it reads from `pick` and take it as ' +
|
|
61
|
+
`the second argument (${SPEC}/03-lists.md "Rows must be pure").`);
|
|
62
|
+
}
|
|
63
|
+
/** A hook hole got something other than a hook result. */
|
|
64
|
+
export function badHook(value) {
|
|
65
|
+
throw new TypeError(`gyral: an element hook position (\${…} inside a start tag) got ${describe(value)}. Only ` +
|
|
66
|
+
`hooks made with defineHook() go there, e.g. <input \${invalid(errors)}> ` +
|
|
67
|
+
`(${SPEC}/02-bindings.md "Element hooks").`);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=warn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warn.js","sourceRoot":"","sources":["../../../src/view/render/warn.ts"],"names":[],"mappings":"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","sourcesContent":["// Development-only errors and warnings of the renderer (view/02-bindings.md \"Child values\",\n// view/03-lists.md \"Keys\", view/09-template-rules.md \"Warnings\"). Every call site is guarded by\n// `if (DEV)`, so production bundles drop this module. Messages say what to write instead.\n\nconst SPEC = 'docs/design-docs/view';\nconst warned = new WeakSet<object>();\n\nconst describe = (value: unknown): string =>\n typeof value === 'function'\n ? 'a function'\n : Array.isArray(value)\n ? 'an array'\n : typeof value === 'object'\n ? `an object (${Object.prototype.toString.call(value).slice(8, -1)})`\n : `a ${typeof value}`;\n\n/** A child hole got a value it can't render: an error in development. */\nexport function badChild(value: unknown): never {\n throw new TypeError(\n `gyral: a child hole got ${describe(value)}, which it can't render. Child holes take ` +\n `text, numbers, html\\`…\\` results, each(…), arrays, raw(…), or null/undefined/false/` +\n `nothing for nothing. Format the value as text, or render it with a template ` +\n `(${SPEC}/02-bindings.md \"Child values\").`,\n );\n}\n\n/** `true` in a child hole, once per part: usually a `cond && x` slip. */\nexport function warnTrue(part: object): void {\n if (warned.has(part)) return;\n warned.add(part);\n console.warn(\n 'gyral: `true` in a child hole renders nothing. It is usually a `cond && x` slip where ' +\n 'cond is a boolean and x is missing; write `cond ? x : nothing` ' +\n `(${SPEC}/02-bindings.md \"Child values\").`,\n );\n}\n\n/** An attribute or text-content hole got an object or function, once per part. */\nexport function warnValue(part: object, value: unknown, where: string): void {\n if (warned.has(part)) return;\n warned.add(part);\n console.warn(\n `gyral: ${where} got ${describe(value)}; it is written as String(value). Pass a string, ` +\n `number or boolean, or null/undefined/nothing to leave it out ` +\n `(${SPEC}/02-bindings.md \"Attribute values\").`,\n );\n}\n\nlet rawWarned = false;\n\n/** `raw()` parsed in the browser, once per page. */\nexport function warnRaw(): void {\n if (rawWarned) return;\n rawWarned = true;\n console.warn(\n 'gyral: raw() rendered in the browser. It works, but every change re-parses the markup; ' +\n 'prefer templates for content that changes, and keep raw() for server-rendered markup ' +\n `(${SPEC}/09-template-rules.md \"Warnings\").`,\n );\n}\n\n/** Keys must be unique strings or numbers: an error in development. */\nexport function badKey(key: unknown, index: number, duplicate: boolean): never {\n const problem = duplicate\n ? `the key ${JSON.stringify(key)} appears twice (again at index ${String(index)})`\n : `the key at index ${String(index)} is ${describe(key)}`;\n throw new Error(\n `gyral: each(): ${problem}. Keys must be unique strings or numbers within a list, such ` +\n `as a stable id: each(items, (x) => x.id, Row) (${SPEC}/03-lists.md \"Keys\").`,\n );\n}\n\n/** A skipped row would render differently: it reads something besides `item` and `pick`. */\nexport function warnImpureRow(row: (...args: never[]) => unknown): void {\n const name = row.name === '' ? 'a row function' : `the row function ${row.name}`;\n console.warn(\n `gyral: each(): ${name} depends on something not passed through \\`item\\` or \\`pick\\`, so ` +\n 'skipped rows would show stale content. Return what it reads from `pick` and take it as ' +\n `the second argument (${SPEC}/03-lists.md \"Rows must be pure\").`,\n );\n}\n\n/** A hook hole got something other than a hook result. */\nexport function badHook(value: unknown): never {\n throw new TypeError(\n `gyral: an element hook position (\\${…} inside a start tag) got ${describe(value)}. Only ` +\n `hooks made with defineHook() go there, e.g. <input \\${invalid(errors)}> ` +\n `(${SPEC}/02-bindings.md \"Element hooks\").`,\n );\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ServerComponent } from '../registry.js';
|
|
2
|
+
import { type Deferred, type Item } from './writer.js';
|
|
3
|
+
/**
|
|
4
|
+
* The text of a shadow component's `<style>` (its CSS texts joined by newlines, `</style`
|
|
5
|
+
* escaped), exactly as written, so `styleHashes()` hashes what the browser sees. `''`: none.
|
|
6
|
+
*/
|
|
7
|
+
export declare function styleText(component: ServerComponent): string;
|
|
8
|
+
/** Writes a deferred component; nested components are deferred again. */
|
|
9
|
+
export declare function expand({ component, input }: Deferred, dev: boolean): Item[];
|