@gyral/core 0.2.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 +87 -0
- package/README.md +7 -5
- 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 -327
- 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 -2
- 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 +7 -12
- package/dist/focus.js +13 -10
- 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 -17
- package/dist/index.js +9 -18
- 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 +11 -4
- 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/{template-whitespace.js → view/normalize/whitespace.js} +24 -34
- 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 +39 -4
- 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/invalid.d.ts +0 -21
- package/dist/invalid.js +0 -70
- package/dist/invalid.js.map +0 -1
- package/dist/lit-html-check.d.ts +0 -6
- package/dist/lit-html-check.js +0 -48
- package/dist/lit-html-check.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/template-whitespace.d.ts +0 -7
- package/dist/template-whitespace.js.map +0 -1
- package/dist/templates.d.ts +0 -5
- package/dist/templates.js +0 -15
- package/dist/templates.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,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[];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Rendering one Gyral component in place (view/06-server.md "Components"): the end of its start
|
|
2
|
+
// tag (light mark, seed, island attributes), then its view, inside a declarative shadow root
|
|
3
|
+
// with the component's CSS (08 "Server") or as light-DOM children (ADR 0014). The parent's
|
|
4
|
+
// children of a shadow component follow in the parent's walk, after the `<template>`.
|
|
5
|
+
import { ISLAND_ATTRIBUTE, LIGHT_ATTRIBUTE, SEED_ATTRIBUTE } from '../attributes.js';
|
|
6
|
+
import { escapeSeed, styleSafe } from './escape.js';
|
|
7
|
+
import { ROOT, Writer } from './writer.js';
|
|
8
|
+
const styleTexts = new WeakMap();
|
|
9
|
+
/**
|
|
10
|
+
* The text of a shadow component's `<style>` (its CSS texts joined by newlines, `</style`
|
|
11
|
+
* escaped), exactly as written, so `styleHashes()` hashes what the browser sees. `''`: none.
|
|
12
|
+
*/
|
|
13
|
+
export function styleText(component) {
|
|
14
|
+
let text = styleTexts.get(component);
|
|
15
|
+
if (text === undefined) {
|
|
16
|
+
text = styleSafe(component.styles.join('\n'));
|
|
17
|
+
styleTexts.set(component, text);
|
|
18
|
+
}
|
|
19
|
+
return text;
|
|
20
|
+
}
|
|
21
|
+
/** Writes a deferred component; nested components are deferred again. */
|
|
22
|
+
export function expand({ component, input }, dev) {
|
|
23
|
+
const { view, seed } = component.render(input);
|
|
24
|
+
const w = new Writer(dev, input.scope);
|
|
25
|
+
let tail = component.light ? ` ${LIGHT_ATTRIBUTE}` : '';
|
|
26
|
+
// Single-quoted, so the JSON's double quotes stay raw (ADR 0012).
|
|
27
|
+
tail += ` ${SEED_ATTRIBUTE}='${escapeSeed(JSON.stringify(seed))}'`;
|
|
28
|
+
if (component.hydrate !== 'load') {
|
|
29
|
+
tail += ` defer-hydration ${ISLAND_ATTRIBUTE}="${component.hydrate}"`;
|
|
30
|
+
}
|
|
31
|
+
w.write(`${tail}>`);
|
|
32
|
+
if (component.light) {
|
|
33
|
+
w.child(view, undefined, ROOT);
|
|
34
|
+
return w.done();
|
|
35
|
+
}
|
|
36
|
+
const css = styleText(component);
|
|
37
|
+
w.write(`<template shadowrootmode="open">${css === '' ? '' : `<style>${css}</style>`}`);
|
|
38
|
+
w.child(view, undefined, ROOT);
|
|
39
|
+
w.write('</template>');
|
|
40
|
+
return w.done();
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.js","sourceRoot":"","sources":["../../../src/view/server/component.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,6FAA6F;AAC7F,2FAA2F;AAC3F,sFAAsF;AACtF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAErF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,EAA4B,MAAM,aAAa,CAAC;AAErE,MAAM,UAAU,GAAG,IAAI,OAAO,EAA2B,CAAC;AAE1D;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,SAA0B;IAClD,IAAI,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACrC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9C,UAAU,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,MAAM,CAAC,EAAE,SAAS,EAAE,KAAK,EAAY,EAAE,GAAY;IACjE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,kEAAkE;IAClE,IAAI,IAAI,IAAI,cAAc,KAAK,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;IACnE,IAAI,SAAS,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QACjC,IAAI,IAAI,oBAAoB,gBAAgB,KAAK,SAAS,CAAC,OAAO,GAAG,CAAC;IACxE,CAAC;IACD,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;IACpB,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QAC/B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAClB,CAAC;IACD,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC,CAAC,KAAK,CAAC,mCAAmC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC,CAAC;IACxF,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;AAClB,CAAC","sourcesContent":["// Rendering one Gyral component in place (view/06-server.md \"Components\"): the end of its start\n// tag (light mark, seed, island attributes), then its view, inside a declarative shadow root\n// with the component's CSS (08 \"Server\") or as light-DOM children (ADR 0014). The parent's\n// children of a shadow component follow in the parent's walk, after the `<template>`.\nimport { ISLAND_ATTRIBUTE, LIGHT_ATTRIBUTE, SEED_ATTRIBUTE } from '../attributes.js';\nimport type { ServerComponent } from '../registry.js';\nimport { escapeSeed, styleSafe } from './escape.js';\nimport { ROOT, Writer, type Deferred, type Item } from './writer.js';\n\nconst styleTexts = new WeakMap<ServerComponent, string>();\n\n/**\n * The text of a shadow component's `<style>` (its CSS texts joined by newlines, `</style`\n * escaped), exactly as written, so `styleHashes()` hashes what the browser sees. `''`: none.\n */\nexport function styleText(component: ServerComponent): string {\n let text = styleTexts.get(component);\n if (text === undefined) {\n text = styleSafe(component.styles.join('\\n'));\n styleTexts.set(component, text);\n }\n return text;\n}\n\n/** Writes a deferred component; nested components are deferred again. */\nexport function expand({ component, input }: Deferred, dev: boolean): Item[] {\n const { view, seed } = component.render(input);\n const w = new Writer(dev, input.scope);\n let tail = component.light ? ` ${LIGHT_ATTRIBUTE}` : '';\n // Single-quoted, so the JSON's double quotes stay raw (ADR 0012).\n tail += ` ${SEED_ATTRIBUTE}='${escapeSeed(JSON.stringify(seed))}'`;\n if (component.hydrate !== 'load') {\n tail += ` defer-hydration ${ISLAND_ATTRIBUTE}=\"${component.hydrate}\"`;\n }\n w.write(`${tail}>`);\n if (component.light) {\n w.child(view, undefined, ROOT);\n return w.done();\n }\n const css = styleText(component);\n w.write(`<template shadowrootmode=\"open\">${css === '' ? '' : `<style>${css}</style>`}`);\n w.child(view, undefined, ROOT);\n w.write('</template>');\n return w.done();\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Text content (child holes, `<textarea>`/`<title>` content). */
|
|
2
|
+
export declare function escapeText(text: string): string;
|
|
3
|
+
/** A double-quoted attribute value. */
|
|
4
|
+
export declare function escapeAttr(value: string): string;
|
|
5
|
+
/** A single-quoted attribute value: the `data-gyral-seed` JSON. */
|
|
6
|
+
export declare const escapeSeed: (json: string) => string;
|
|
7
|
+
/** CSS for a `<style>` element: `</style` (any case) would end it; `<\/style` is the same CSS. */
|
|
8
|
+
export declare const styleSafe: (css: string) => string;
|
|
9
|
+
/** HTML whitespace (WHATWG "ASCII whitespace"): text made only of it stays in table structure. */
|
|
10
|
+
export declare const onlyWhitespace: (text: string) => boolean;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Escaping for the server renderer (view/06-server.md "Escaping"). Text escapes `&`, `<` and
|
|
2
|
+
// `>`; double-quoted attribute values escape `&`, `"`, `<` and `>`; the single-quoted seed
|
|
3
|
+
// attribute escapes `&`, `'`, `<` and `>` (so its JSON's double quotes stay raw). Only `&` and
|
|
4
|
+
// the quote can end a quoted value; `<` and `>` are escaped too (as newer revisions of WHATWG
|
|
5
|
+
// HTML's "Serializing HTML fragments" do), so no markup appears raw in an attribute, whatever
|
|
6
|
+
// later reads the page (raw-text contexts, naive tooling, filters).
|
|
7
|
+
const TEXT = /[&<>]/g;
|
|
8
|
+
const ATTR = /[&"<>]/g;
|
|
9
|
+
const SEED = /[&'<>]/g;
|
|
10
|
+
const ENTITY = {
|
|
11
|
+
'&': '&',
|
|
12
|
+
'<': '<',
|
|
13
|
+
'>': '>',
|
|
14
|
+
'"': '"',
|
|
15
|
+
"'": ''',
|
|
16
|
+
};
|
|
17
|
+
const entity = (c) => ENTITY[c] ?? c;
|
|
18
|
+
/** Text content (child holes, `<textarea>`/`<title>` content). */
|
|
19
|
+
export function escapeText(text) {
|
|
20
|
+
TEXT.lastIndex = 0;
|
|
21
|
+
return TEXT.test(text) ? text.replace(TEXT, entity) : text;
|
|
22
|
+
}
|
|
23
|
+
/** A double-quoted attribute value. */
|
|
24
|
+
export function escapeAttr(value) {
|
|
25
|
+
ATTR.lastIndex = 0;
|
|
26
|
+
return ATTR.test(value) ? value.replace(ATTR, entity) : value;
|
|
27
|
+
}
|
|
28
|
+
/** A single-quoted attribute value: the `data-gyral-seed` JSON. */
|
|
29
|
+
export const escapeSeed = (json) => json.replace(SEED, entity);
|
|
30
|
+
/** CSS for a `<style>` element: `</style` (any case) would end it; `<\/style` is the same CSS. */
|
|
31
|
+
export const styleSafe = (css) => css.replace(/<\/(style)/gi, '<\\/$1');
|
|
32
|
+
/** HTML whitespace (WHATWG "ASCII whitespace"): text made only of it stays in table structure. */
|
|
33
|
+
export const onlyWhitespace = (text) => !/[^\t\n\f\r ]/.test(text);
|
|
34
|
+
//# sourceMappingURL=escape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"escape.js","sourceRoot":"","sources":["../../../src/view/server/escape.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,2FAA2F;AAC3F,+FAA+F;AAC/F,8FAA8F;AAC9F,8FAA8F;AAC9F,oEAAoE;AAEpE,MAAM,IAAI,GAAG,QAAQ,CAAC;AACtB,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,IAAI,GAAG,SAAS,CAAC;AAEvB,MAAM,MAAM,GAAqC;IAC/C,GAAG,EAAE,OAAO;IACZ,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,QAAQ;IACb,GAAG,EAAE,OAAO;CACb,CAAC;AAEF,MAAM,MAAM,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAErD,kEAAkE;AAClE,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;IACnB,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAChE,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAE/E,kGAAkG;AAClG,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;AAExF,kGAAkG;AAClG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC","sourcesContent":["// Escaping for the server renderer (view/06-server.md \"Escaping\"). Text escapes `&`, `<` and\n// `>`; double-quoted attribute values escape `&`, `\"`, `<` and `>`; the single-quoted seed\n// attribute escapes `&`, `'`, `<` and `>` (so its JSON's double quotes stay raw). Only `&` and\n// the quote can end a quoted value; `<` and `>` are escaped too (as newer revisions of WHATWG\n// HTML's \"Serializing HTML fragments\" do), so no markup appears raw in an attribute, whatever\n// later reads the page (raw-text contexts, naive tooling, filters).\n\nconst TEXT = /[&<>]/g;\nconst ATTR = /[&\"<>]/g;\nconst SEED = /[&'<>]/g;\n\nconst ENTITY: Readonly<Record<string, string>> = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n};\n\nconst entity = (c: string): string => ENTITY[c] ?? c;\n\n/** Text content (child holes, `<textarea>`/`<title>` content). */\nexport function escapeText(text: string): string {\n TEXT.lastIndex = 0;\n return TEXT.test(text) ? text.replace(TEXT, entity) : text;\n}\n\n/** A double-quoted attribute value. */\nexport function escapeAttr(value: string): string {\n ATTR.lastIndex = 0;\n return ATTR.test(value) ? value.replace(ATTR, entity) : value;\n}\n\n/** A single-quoted attribute value: the `data-gyral-seed` JSON. */\nexport const escapeSeed = (json: string): string => json.replace(SEED, entity);\n\n/** CSS for a `<style>` element: `</style` (any case) would end it; `<\\/style` is the same CSS. */\nexport const styleSafe = (css: string): string => css.replace(/<\\/(style)/gi, '<\\\\/$1');\n\n/** HTML whitespace (WHATWG \"ASCII whitespace\"): text made only of it stays in table structure. */\nexport const onlyWhitespace = (text: string): boolean => !/[^\\t\\n\\f\\r ]/.test(text);\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ChildValue } from '../render/values.js';
|
|
2
|
+
export interface ServerRenderOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Development markers (`<!--gyral:ID-->` before each template instance, for hydration's
|
|
5
|
+
* checks, 07) and development checks. Default: on in development builds (the `development`
|
|
6
|
+
* export condition, as for the client), off otherwise.
|
|
7
|
+
*/
|
|
8
|
+
readonly dev?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Renders `value` to HTML chunks, lazily: each step writes up to the next component boundary.
|
|
12
|
+
* Every component's `init` and view run in the step that writes it, so a caller can wrap each
|
|
13
|
+
* step in a per-request scope (ADR 0013).
|
|
14
|
+
*/
|
|
15
|
+
export declare function render(value: ChildValue, options?: ServerRenderOptions): Iterable<string>;
|
|
16
|
+
/** Renders `value` to one string. */
|
|
17
|
+
export declare function renderToString(value: ChildValue, options?: ServerRenderOptions): string;
|
|
18
|
+
/**
|
|
19
|
+
* `'sha256-…'` of a `<style>` element's text, for a CSP `style-src` (cached per text).
|
|
20
|
+
* Synchronous (sha256.ts), so a page can build its policy while it renders.
|
|
21
|
+
*/
|
|
22
|
+
export declare function styleHashSync(text: string): string;
|
|
23
|
+
/** `styleHashSync`, as a promise (the API before it existed). */
|
|
24
|
+
export declare const styleHash: (text: string) => Promise<string>;
|
|
25
|
+
/** Tag → `<style>` text of every registered shadow component with CSS (08 "Server"). */
|
|
26
|
+
export declare function componentStyles(): ReadonlyMap<string, string>;
|
|
27
|
+
/** The hashes of every registered shadow component's `<style>` (08 "Server"), deduplicated. */
|
|
28
|
+
export declare function styleHashes(): Promise<readonly string[]>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// The server renderer (view/06-server.md "API"): synchronous, chunked, runtime-agnostic (no
|
|
2
|
+
// DOM, no Node-only APIs: a JavaScript SHA-256 for the style hashes). `@gyral/core/server` wraps these,
|
|
3
|
+
// registering recorded specs first; code outside view/ may import only this module of view/server/.
|
|
4
|
+
import { DEV } from '../flags.js';
|
|
5
|
+
import { serverComponents } from '../registry.js';
|
|
6
|
+
import { expand, styleText } from './component.js';
|
|
7
|
+
import { sha256 } from './sha256.js';
|
|
8
|
+
import { ROOT, Writer } from './writer.js';
|
|
9
|
+
function push(stack, items) {
|
|
10
|
+
for (let i = items.length - 1; i >= 0; i--)
|
|
11
|
+
stack.push(items[i]);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Renders `value` to HTML chunks, lazily: each step writes up to the next component boundary.
|
|
15
|
+
* Every component's `init` and view run in the step that writes it, so a caller can wrap each
|
|
16
|
+
* step in a per-request scope (ADR 0013).
|
|
17
|
+
*/
|
|
18
|
+
export function* render(value, options = {}) {
|
|
19
|
+
const dev = options.dev ?? DEV;
|
|
20
|
+
const root = new Writer(dev, undefined);
|
|
21
|
+
root.child(value, undefined, ROOT);
|
|
22
|
+
const stack = [];
|
|
23
|
+
push(stack, root.done());
|
|
24
|
+
for (let item = stack.pop(); item !== undefined; item = stack.pop()) {
|
|
25
|
+
if (typeof item === 'string')
|
|
26
|
+
yield item;
|
|
27
|
+
else
|
|
28
|
+
push(stack, expand(item, dev));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Renders `value` to one string. */
|
|
32
|
+
export function renderToString(value, options) {
|
|
33
|
+
let html = '';
|
|
34
|
+
for (const chunk of render(value, options))
|
|
35
|
+
html += chunk;
|
|
36
|
+
return html;
|
|
37
|
+
}
|
|
38
|
+
const hashes = new Map();
|
|
39
|
+
/**
|
|
40
|
+
* `'sha256-…'` of a `<style>` element's text, for a CSP `style-src` (cached per text).
|
|
41
|
+
* Synchronous (sha256.ts), so a page can build its policy while it renders.
|
|
42
|
+
*/
|
|
43
|
+
export function styleHashSync(text) {
|
|
44
|
+
let hash = hashes.get(text);
|
|
45
|
+
if (hash === undefined) {
|
|
46
|
+
// The parser turns CR and CRLF into LF before the browser hashes the element's text.
|
|
47
|
+
const digest = sha256(new TextEncoder().encode(text.replace(/\r\n?/g, '\n')));
|
|
48
|
+
let binary = '';
|
|
49
|
+
for (const byte of digest)
|
|
50
|
+
binary += String.fromCharCode(byte);
|
|
51
|
+
hash = `'sha256-${btoa(binary)}'`;
|
|
52
|
+
hashes.set(text, hash);
|
|
53
|
+
}
|
|
54
|
+
return hash;
|
|
55
|
+
}
|
|
56
|
+
/** `styleHashSync`, as a promise (the API before it existed). */
|
|
57
|
+
export const styleHash = (text) => Promise.resolve(styleHashSync(text));
|
|
58
|
+
/** Tag → `<style>` text of every registered shadow component with CSS (08 "Server"). */
|
|
59
|
+
export function componentStyles() {
|
|
60
|
+
const styles = new Map();
|
|
61
|
+
for (const component of serverComponents()) {
|
|
62
|
+
const text = styleText(component);
|
|
63
|
+
if (text !== '')
|
|
64
|
+
styles.set(component.tag, text);
|
|
65
|
+
}
|
|
66
|
+
return styles;
|
|
67
|
+
}
|
|
68
|
+
/** The hashes of every registered shadow component's `<style>` (08 "Server"), deduplicated. */
|
|
69
|
+
export function styleHashes() {
|
|
70
|
+
return Promise.resolve([...new Set([...componentStyles().values()].map(styleHashSync))]);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/view/server/index.ts"],"names":[],"mappings":"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","sourcesContent":["// The server renderer (view/06-server.md \"API\"): synchronous, chunked, runtime-agnostic (no\n// DOM, no Node-only APIs: a JavaScript SHA-256 for the style hashes). `@gyral/core/server` wraps these,\n// registering recorded specs first; code outside view/ may import only this module of view/server/.\nimport { DEV } from '../flags.js';\nimport { serverComponents } from '../registry.js';\nimport type { ChildValue } from '../render/values.js';\nimport { expand, styleText } from './component.js';\nimport { sha256 } from './sha256.js';\nimport { ROOT, Writer, type Item } from './writer.js';\n\nexport interface ServerRenderOptions {\n /**\n * Development markers (`<!--gyral:ID-->` before each template instance, for hydration's\n * checks, 07) and development checks. Default: on in development builds (the `development`\n * export condition, as for the client), off otherwise.\n */\n readonly dev?: boolean;\n}\n\nfunction push(stack: Item[], items: readonly Item[]): void {\n for (let i = items.length - 1; i >= 0; i--) stack.push(items[i] as Item);\n}\n\n/**\n * Renders `value` to HTML chunks, lazily: each step writes up to the next component boundary.\n * Every component's `init` and view run in the step that writes it, so a caller can wrap each\n * step in a per-request scope (ADR 0013).\n */\nexport function* render(value: ChildValue, options: ServerRenderOptions = {}): Iterable<string> {\n const dev = options.dev ?? DEV;\n const root = new Writer(dev, undefined);\n root.child(value, undefined, ROOT);\n const stack: Item[] = [];\n push(stack, root.done());\n for (let item = stack.pop(); item !== undefined; item = stack.pop()) {\n if (typeof item === 'string') yield item;\n else push(stack, expand(item, dev));\n }\n}\n\n/** Renders `value` to one string. */\nexport function renderToString(value: ChildValue, options?: ServerRenderOptions): string {\n let html = '';\n for (const chunk of render(value, options)) html += chunk;\n return html;\n}\n\nconst hashes = new Map<string, string>();\n\n/**\n * `'sha256-…'` of a `<style>` element's text, for a CSP `style-src` (cached per text).\n * Synchronous (sha256.ts), so a page can build its policy while it renders.\n */\nexport function styleHashSync(text: string): string {\n let hash = hashes.get(text);\n if (hash === undefined) {\n // The parser turns CR and CRLF into LF before the browser hashes the element's text.\n const digest = sha256(new TextEncoder().encode(text.replace(/\\r\\n?/g, '\\n')));\n let binary = '';\n for (const byte of digest) binary += String.fromCharCode(byte);\n hash = `'sha256-${btoa(binary)}'`;\n hashes.set(text, hash);\n }\n return hash;\n}\n\n/** `styleHashSync`, as a promise (the API before it existed). */\nexport const styleHash = (text: string): Promise<string> => Promise.resolve(styleHashSync(text));\n\n/** Tag → `<style>` text of every registered shadow component with CSS (08 \"Server\"). */\nexport function componentStyles(): ReadonlyMap<string, string> {\n const styles = new Map<string, string>();\n for (const component of serverComponents()) {\n const text = styleText(component);\n if (text !== '') styles.set(component.tag, text);\n }\n return styles;\n}\n\n/** The hashes of every registered shadow component's `<style>` (08 \"Server\"), deduplicated. */\nexport function styleHashes(): Promise<readonly string[]> {\n return Promise.resolve([...new Set([...componentStyles().values()].map(styleHashSync))]);\n}\n"]}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// SHA-256 (FIPS 180-4) in plain JavaScript, for CSP style hashes (view/06-server.md "CSP").
|
|
2
|
+
// Synchronous, unlike WebCrypto's `digest`, so `@gyral/ssr`'s `renderPage` can build the
|
|
3
|
+
// policy at render time, after the page's components are registered, and still return its
|
|
4
|
+
// Response synchronously. Runtime-agnostic (no `node:crypto`); server-only, never in client
|
|
5
|
+
// bundles. Checked against `node:crypto` (sha256.node.test.ts).
|
|
6
|
+
/** Round constants: the first 32 bits of the fractional parts of the cube roots of the first 64 primes. */
|
|
7
|
+
const K = new Uint32Array([
|
|
8
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
9
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
10
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
11
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
12
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
13
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
14
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
15
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
16
|
+
]);
|
|
17
|
+
/** Initial hash: the first 32 bits of the fractional parts of the square roots of the first 8 primes. */
|
|
18
|
+
const H0 = [
|
|
19
|
+
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
|
20
|
+
];
|
|
21
|
+
const rotr = (x, n) => (x >>> n) | (x << (32 - n));
|
|
22
|
+
/** The SHA-256 digest of `bytes` (32 bytes). */
|
|
23
|
+
export function sha256(bytes) {
|
|
24
|
+
// Padding: 0x80, zeros, then the bit length as a 64-bit big-endian number.
|
|
25
|
+
const blocks = (bytes.length + 9 + 63) >> 6;
|
|
26
|
+
const m = new Uint8Array(blocks * 64);
|
|
27
|
+
m.set(bytes);
|
|
28
|
+
m[bytes.length] = 0x80;
|
|
29
|
+
const view = new DataView(m.buffer);
|
|
30
|
+
const bits = bytes.length * 8;
|
|
31
|
+
view.setUint32(m.length - 8, Math.floor(bits / 0x100000000));
|
|
32
|
+
view.setUint32(m.length - 4, bits >>> 0);
|
|
33
|
+
const h = new Uint32Array(H0);
|
|
34
|
+
const w = new Uint32Array(64);
|
|
35
|
+
for (let off = 0; off < m.length; off += 64) {
|
|
36
|
+
for (let t = 0; t < 16; t++)
|
|
37
|
+
w[t] = view.getUint32(off + t * 4);
|
|
38
|
+
for (let t = 16; t < 64; t++) {
|
|
39
|
+
const x = w[t - 15];
|
|
40
|
+
const y = w[t - 2];
|
|
41
|
+
const s0 = rotr(x, 7) ^ rotr(x, 18) ^ (x >>> 3);
|
|
42
|
+
const s1 = rotr(y, 17) ^ rotr(y, 19) ^ (y >>> 10);
|
|
43
|
+
w[t] = w[t - 16] + s0 + w[t - 7] + s1;
|
|
44
|
+
}
|
|
45
|
+
let [a, b, c, d, e, f, g, k] = Array.from(h);
|
|
46
|
+
for (let t = 0; t < 64; t++) {
|
|
47
|
+
const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
|
|
48
|
+
const t1 = (k + s1 + ((e & f) ^ (~e & g)) + K[t] + w[t]) | 0;
|
|
49
|
+
const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
|
|
50
|
+
const t2 = (s0 + ((a & b) ^ (a & c) ^ (b & c))) | 0;
|
|
51
|
+
k = g;
|
|
52
|
+
g = f;
|
|
53
|
+
f = e;
|
|
54
|
+
e = (d + t1) | 0;
|
|
55
|
+
d = c;
|
|
56
|
+
c = b;
|
|
57
|
+
b = a;
|
|
58
|
+
a = (t1 + t2) | 0;
|
|
59
|
+
}
|
|
60
|
+
h[0] = h[0] + a;
|
|
61
|
+
h[1] = h[1] + b;
|
|
62
|
+
h[2] = h[2] + c;
|
|
63
|
+
h[3] = h[3] + d;
|
|
64
|
+
h[4] = h[4] + e;
|
|
65
|
+
h[5] = h[5] + f;
|
|
66
|
+
h[6] = h[6] + g;
|
|
67
|
+
h[7] = h[7] + k;
|
|
68
|
+
}
|
|
69
|
+
const out = new Uint8Array(32);
|
|
70
|
+
const outView = new DataView(out.buffer);
|
|
71
|
+
for (let i = 0; i < 8; i++)
|
|
72
|
+
outView.setUint32(i * 4, h[i]);
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=sha256.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../../src/view/server/sha256.ts"],"names":[],"mappings":"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","sourcesContent":["// SHA-256 (FIPS 180-4) in plain JavaScript, for CSP style hashes (view/06-server.md \"CSP\").\n// Synchronous, unlike WebCrypto's `digest`, so `@gyral/ssr`'s `renderPage` can build the\n// policy at render time, after the page's components are registered, and still return its\n// Response synchronously. Runtime-agnostic (no `node:crypto`); server-only, never in client\n// bundles. Checked against `node:crypto` (sha256.node.test.ts).\n\n/** Round constants: the first 32 bits of the fractional parts of the cube roots of the first 64 primes. */\nconst K = new Uint32Array([\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n]);\n\n/** Initial hash: the first 32 bits of the fractional parts of the square roots of the first 8 primes. */\nconst H0 = [\n 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\n];\n\n/** The eight working variables. */\ntype Words = [number, number, number, number, number, number, number, number];\n\nconst rotr = (x: number, n: number): number => (x >>> n) | (x << (32 - n));\n\n/** The SHA-256 digest of `bytes` (32 bytes). */\nexport function sha256(bytes: Uint8Array): Uint8Array {\n // Padding: 0x80, zeros, then the bit length as a 64-bit big-endian number.\n const blocks = (bytes.length + 9 + 63) >> 6;\n const m = new Uint8Array(blocks * 64);\n m.set(bytes);\n m[bytes.length] = 0x80;\n const view = new DataView(m.buffer);\n const bits = bytes.length * 8;\n view.setUint32(m.length - 8, Math.floor(bits / 0x100000000));\n view.setUint32(m.length - 4, bits >>> 0);\n const h = new Uint32Array(H0);\n const w = new Uint32Array(64);\n for (let off = 0; off < m.length; off += 64) {\n for (let t = 0; t < 16; t++) w[t] = view.getUint32(off + t * 4);\n for (let t = 16; t < 64; t++) {\n const x = w[t - 15] as number;\n const y = w[t - 2] as number;\n const s0 = rotr(x, 7) ^ rotr(x, 18) ^ (x >>> 3);\n const s1 = rotr(y, 17) ^ rotr(y, 19) ^ (y >>> 10);\n w[t] = (w[t - 16] as number) + s0 + (w[t - 7] as number) + s1;\n }\n let [a, b, c, d, e, f, g, k] = Array.from(h) as Words;\n for (let t = 0; t < 64; t++) {\n const s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);\n const t1 = (k + s1 + ((e & f) ^ (~e & g)) + (K[t] as number) + (w[t] as number)) | 0;\n const s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);\n const t2 = (s0 + ((a & b) ^ (a & c) ^ (b & c))) | 0;\n k = g;\n g = f;\n f = e;\n e = (d + t1) | 0;\n d = c;\n c = b;\n b = a;\n a = (t1 + t2) | 0;\n }\n h[0] = (h[0] as number) + a;\n h[1] = (h[1] as number) + b;\n h[2] = (h[2] as number) + c;\n h[3] = (h[3] as number) + d;\n h[4] = (h[4] as number) + e;\n h[5] = (h[5] as number) + f;\n h[6] = (h[6] as number) + g;\n h[7] = (h[7] as number) + k;\n }\n const out = new Uint8Array(32);\n const outView = new DataView(out.buffer);\n for (let i = 0; i < 8; i++) outView.setUint32(i * 4, h[i] as number);\n return out;\n}\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { Segment } from '../normalize/types.js';
|
|
2
|
+
import { type ServerComponent, type ServerProvider, type ServerRenderInput } from '../registry.js';
|
|
3
|
+
/** A component whose content is written later, in its own render step. */
|
|
4
|
+
export interface Deferred {
|
|
5
|
+
readonly component: ServerComponent;
|
|
6
|
+
readonly input: ServerRenderInput;
|
|
7
|
+
}
|
|
8
|
+
/** What a walk produces: markup, with deferred components in document order. */
|
|
9
|
+
export type Item = string | Deferred;
|
|
10
|
+
/** A custom element's start tag while its attribute holes are written. */
|
|
11
|
+
export interface Opening {
|
|
12
|
+
readonly tag: string;
|
|
13
|
+
readonly component: ServerComponent | undefined;
|
|
14
|
+
readonly provider: ServerProvider | undefined;
|
|
15
|
+
readonly attributes: Record<string, string>;
|
|
16
|
+
readonly properties: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
/** An open custom element until its end tag: plain, a provider, or a light component. */
|
|
19
|
+
export type Frame = {
|
|
20
|
+
readonly k: 'plain';
|
|
21
|
+
} | {
|
|
22
|
+
readonly k: 'provider';
|
|
23
|
+
readonly outer: unknown;
|
|
24
|
+
} | {
|
|
25
|
+
readonly k: 'light';
|
|
26
|
+
readonly tag: string;
|
|
27
|
+
readonly items: number;
|
|
28
|
+
};
|
|
29
|
+
export declare const PLAIN: Frame;
|
|
30
|
+
export declare class Markup {
|
|
31
|
+
protected readonly dev: boolean;
|
|
32
|
+
protected scope: unknown;
|
|
33
|
+
protected buf: string;
|
|
34
|
+
protected readonly items: Item[];
|
|
35
|
+
/**
|
|
36
|
+
* `dev`: development markers and checks. `scope`: the nearest provider's scope, passed to
|
|
37
|
+
* components (undefined: the request's).
|
|
38
|
+
*/
|
|
39
|
+
constructor(dev: boolean, scope: unknown);
|
|
40
|
+
write(markup: string): void;
|
|
41
|
+
/** The markup and deferred components written so far. */
|
|
42
|
+
done(): Item[];
|
|
43
|
+
private flush;
|
|
44
|
+
/** `name=${v}` or `name="a ${v} b"`; returns the index of the next value. */
|
|
45
|
+
protected attr(s: Extract<Segment, {
|
|
46
|
+
k: 'attr';
|
|
47
|
+
}>, values: readonly unknown[], at: number, opening: Opening | undefined): number;
|
|
48
|
+
private valued;
|
|
49
|
+
/** A present boolean attribute (`?name`, or `true` from a hook's server half). */
|
|
50
|
+
protected bare(name: string, opening: Opening | undefined): void;
|
|
51
|
+
/** An element hook: its server half's attributes (02 "Element hooks"). */
|
|
52
|
+
protected hook(v: unknown, opening: Opening | undefined): void;
|
|
53
|
+
/** A custom element's start tag: a Gyral component, a provider, or a plain element. */
|
|
54
|
+
protected open(tag: string, html: string, attrs: readonly (readonly [string, string])[]): Opening | undefined;
|
|
55
|
+
protected openEnd(opening: Opening | undefined): Frame;
|
|
56
|
+
protected close(frame: Frame, tag: string): void;
|
|
57
|
+
}
|