@gyral/core 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +129 -0
- package/NOTICE +19 -0
- package/README.md +35 -8
- package/dist/call.d.ts +32 -0
- package/dist/call.js +63 -0
- package/dist/call.js.map +1 -0
- package/dist/children.d.ts +30 -5
- package/dist/children.js +26 -4
- package/dist/children.js.map +1 -1
- package/dist/cli/gyral-types.d.ts +2 -0
- package/dist/cli/gyral-types.js +23 -0
- package/dist/cli/gyral-types.js.map +1 -0
- package/dist/command.d.ts +54 -12
- package/dist/command.js +31 -11
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +23 -0
- package/dist/compiler/ast.js +149 -0
- package/dist/compiler/ast.js.map +1 -0
- package/dist/compiler/compile.d.ts +41 -0
- package/dist/compiler/compile.js +148 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/component-entries.d.ts +7 -0
- package/dist/compiler/component-entries.js +42 -0
- package/dist/compiler/component-entries.js.map +1 -0
- package/dist/compiler/components.d.ts +4 -0
- package/dist/compiler/components.js +182 -0
- package/dist/compiler/components.js.map +1 -0
- package/dist/compiler/facts.d.ts +31 -0
- package/dist/compiler/facts.js +285 -0
- package/dist/compiler/facts.js.map +1 -0
- package/dist/compiler/features.d.ts +34 -0
- package/dist/compiler/features.js +158 -0
- package/dist/compiler/features.js.map +1 -0
- package/dist/compiler/hooks.d.ts +22 -0
- package/dist/compiler/hooks.js +241 -0
- package/dist/compiler/hooks.js.map +1 -0
- package/dist/compiler/loader-source.d.ts +14 -0
- package/dist/compiler/loader-source.js +86 -0
- package/dist/compiler/loader-source.js.map +1 -0
- package/dist/compiler/locate.d.ts +14 -0
- package/dist/compiler/locate.js +78 -0
- package/dist/compiler/locate.js.map +1 -0
- package/dist/compiler/parse5-check.d.ts +21 -0
- package/dist/compiler/parse5-check.js +60 -0
- package/dist/compiler/parse5-check.js.map +1 -0
- package/dist/compiler/prop-schemas.d.ts +4 -0
- package/dist/compiler/prop-schemas.js +108 -0
- package/dist/compiler/prop-schemas.js.map +1 -0
- package/dist/compiler/scan.d.ts +41 -0
- package/dist/compiler/scan.js +160 -0
- package/dist/compiler/scan.js.map +1 -0
- package/dist/compiler/scope.d.ts +8 -0
- package/dist/compiler/scope.js +116 -0
- package/dist/compiler/scope.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/compiler/tag-map.d.ts +41 -0
- package/dist/compiler/tag-map.js +126 -0
- package/dist/compiler/tag-map.js.map +1 -0
- package/dist/components-ready.d.ts +7 -0
- package/dist/components-ready.js +19 -0
- package/dist/components-ready.js.map +1 -0
- package/dist/define.d.ts +13 -4
- package/dist/define.js +35 -331
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +13 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +2 -0
- package/dist/devtools-off.js +2 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +4 -0
- package/dist/devtools.js +17 -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-internals.d.ts +1 -0
- package/dist/element-internals.js +11 -0
- package/dist/element-internals.js.map +1 -0
- package/dist/element-types.d.ts +11 -5
- package/dist/element-types.js.map +1 -1
- package/dist/element.d.ts +3 -0
- package/dist/element.js +322 -0
- package/dist/element.js.map +1 -0
- package/dist/error-view.d.ts +10 -0
- package/dist/error-view.js +30 -0
- package/dist/error-view.js.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +47 -0
- package/dist/errors.js.map +1 -0
- package/dist/errors.json +289 -0
- package/dist/eslint/imports.d.ts +26 -0
- package/dist/eslint/imports.js +78 -0
- package/dist/eslint/imports.js.map +1 -0
- package/dist/eslint/index.d.ts +16 -0
- package/dist/eslint/index.js +23 -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 +6 -0
- package/dist/eslint/template-rule.js +76 -0
- package/dist/eslint/template-rule.js.map +1 -0
- package/dist/eslint/unused-intent-rule.d.ts +2 -0
- package/dist/eslint/unused-intent-rule.js +186 -0
- package/dist/eslint/unused-intent-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 +13 -12
- package/dist/focus.js +44 -11
- package/dist/focus.js.map +1 -1
- package/dist/form-associated.d.ts +46 -0
- package/dist/form-associated.js +77 -0
- package/dist/form-associated.js.map +1 -0
- package/dist/forms.d.ts +42 -30
- package/dist/forms.js +85 -41
- package/dist/forms.js.map +1 -1
- package/dist/frame-lane.d.ts +11 -0
- package/dist/frame-lane.js +28 -0
- package/dist/frame-lane.js.map +1 -0
- package/dist/head.d.ts +61 -0
- package/dist/head.js +85 -0
- package/dist/head.js.map +1 -0
- 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/host-model.d.ts +77 -0
- package/dist/host-model.js +278 -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-loader.d.ts +13 -0
- package/dist/hydration-loader.js +58 -0
- package/dist/hydration-loader.js.map +1 -0
- package/dist/hydration-off.d.ts +8 -0
- package/dist/hydration-off.js +25 -0
- package/dist/hydration-off.js.map +1 -0
- package/dist/hydration.d.ts +3 -21
- package/dist/hydration.js +14 -63
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +24 -36
- package/dist/index.js +14 -32
- package/dist/index.js.map +1 -1
- package/dist/indexeddb-types.d.ts +97 -0
- package/dist/indexeddb-types.js +2 -0
- package/dist/indexeddb-types.js.map +1 -0
- package/dist/indexeddb.d.ts +5 -0
- package/dist/indexeddb.js +118 -0
- package/dist/indexeddb.js.map +1 -0
- package/dist/intent.d.ts +62 -17
- package/dist/intent.js +193 -100
- package/dist/intent.js.map +1 -1
- package/dist/internal/indexeddb-open.d.ts +8 -0
- package/dist/internal/indexeddb-open.js +96 -0
- package/dist/internal/indexeddb-open.js.map +1 -0
- package/dist/internal/indexeddb-transaction.d.ts +4 -0
- package/dist/internal/indexeddb-transaction.js +134 -0
- package/dist/internal/indexeddb-transaction.js.map +1 -0
- package/dist/internal/interpreter.d.ts +15 -1
- package/dist/internal/interpreter.js +42 -47
- package/dist/internal/interpreter.js.map +1 -1
- package/dist/internal/token.d.ts +1 -0
- package/dist/internal/token.js +7 -0
- package/dist/internal/token.js.map +1 -0
- package/dist/internal.d.ts +20 -0
- package/dist/internal.js +22 -0
- package/dist/internal.js.map +1 -0
- package/dist/invoker-fallback-used.d.ts +4 -0
- package/dist/invoker-fallback-used.js +10 -0
- package/dist/invoker-fallback-used.js.map +1 -0
- package/dist/invoker-fallback.d.ts +4 -0
- package/dist/invoker-fallback.js +15 -0
- package/dist/invoker-fallback.js.map +1 -0
- 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 +4 -53
- package/dist/light-dom.js +5 -100
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +89 -0
- package/dist/prop.js +41 -0
- package/dist/prop.js.map +1 -0
- package/dist/props.d.ts +57 -21
- package/dist/props.js +157 -34
- package/dist/props.js.map +1 -1
- package/dist/retry.d.ts +15 -0
- package/dist/retry.js +48 -0
- package/dist/retry.js.map +1 -0
- package/dist/scheduler.d.ts +43 -0
- package/dist/scheduler.js +212 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/script-json.d.ts +2 -0
- package/dist/script-json.js +13 -0
- package/dist/script-json.js.map +1 -0
- package/dist/server-component.d.ts +10 -0
- package/dist/server-component.js +133 -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 +34 -0
- package/dist/server.js +59 -0
- package/dist/server.js.map +1 -0
- package/dist/settled.d.ts +11 -0
- package/dist/settled.js +62 -0
- package/dist/settled.js.map +1 -0
- package/dist/spec-features-used.d.ts +21 -0
- package/dist/spec-features-used.js +50 -0
- package/dist/spec-features-used.js.map +1 -0
- package/dist/spec-features.d.ts +28 -0
- package/dist/spec-features.js +42 -0
- package/dist/spec-features.js.map +1 -0
- package/dist/states.d.ts +3 -5
- package/dist/states.js +22 -11
- package/dist/states.js.map +1 -1
- package/dist/storage.d.ts +69 -0
- package/dist/storage.js +158 -0
- package/dist/storage.js.map +1 -0
- package/dist/store-binding.d.ts +6 -3
- package/dist/store-binding.js +7 -8
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +8 -11
- package/dist/store-scope.js +15 -40
- package/dist/store-scope.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.js +45 -10
- 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/subscription.d.ts +35 -0
- package/dist/subscription.js +74 -0
- package/dist/subscription.js.map +1 -0
- package/dist/subscriptions.d.ts +26 -0
- package/dist/subscriptions.js +98 -0
- package/dist/subscriptions.js.map +1 -0
- package/dist/transitions.d.ts +5 -7
- package/dist/transitions.js +17 -20
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +142 -49
- package/dist/types.js.map +1 -1
- package/dist/use-dialogs.d.ts +2 -0
- package/dist/use-dialogs.js +9 -0
- package/dist/use-dialogs.js.map +1 -0
- package/dist/use-disposal.d.ts +2 -0
- package/dist/use-disposal.js +9 -0
- package/dist/use-disposal.js.map +1 -0
- package/dist/use-error-view.d.ts +2 -0
- package/dist/use-error-view.js +9 -0
- package/dist/use-error-view.js.map +1 -0
- package/dist/use-errored.d.ts +2 -0
- package/dist/use-errored.js +9 -0
- package/dist/use-errored.js.map +1 -0
- package/dist/use-form-associated.d.ts +2 -0
- package/dist/use-form-associated.js +7 -0
- package/dist/use-form-associated.js.map +1 -0
- package/dist/use-frame-lane.d.ts +2 -0
- package/dist/use-frame-lane.js +10 -0
- package/dist/use-frame-lane.js.map +1 -0
- package/dist/use-invokers.d.ts +2 -0
- package/dist/use-invokers.js +10 -0
- package/dist/use-invokers.js.map +1 -0
- package/dist/use-states.d.ts +2 -0
- package/dist/use-states.js +10 -0
- package/dist/use-states.js.map +1 -0
- package/dist/use-subscriptions.d.ts +2 -0
- package/dist/use-subscriptions.js +10 -0
- package/dist/use-subscriptions.js.map +1 -0
- package/dist/use-transitions.d.ts +2 -0
- package/dist/use-transitions.js +10 -0
- package/dist/use-transitions.js.map +1 -0
- package/dist/view/attributes.d.ts +11 -0
- package/dist/view/attributes.js +15 -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 +26 -0
- package/dist/view/index.js +27 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/loc.d.ts +9 -0
- package/dist/view/loc.js +50 -0
- package/dist/view/loc.js.map +1 -0
- package/dist/view/message.d.ts +17 -0
- package/dist/view/message.js +40 -0
- package/dist/view/message.js.map +1 -0
- package/dist/view/messages.d.ts +43 -0
- package/dist/view/messages.js +84 -0
- package/dist/view/messages.js.map +1 -0
- package/dist/view/normalize/check.d.ts +23 -0
- package/dist/view/normalize/check.js +81 -0
- package/dist/view/normalize/check.js.map +1 -0
- package/dist/view/normalize/emit.d.ts +15 -0
- package/dist/view/normalize/emit.js +165 -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 +10 -0
- package/dist/view/normalize/id.js +55 -0
- package/dist/view/normalize/id.js.map +1 -0
- package/dist/view/normalize/normalize.d.ts +18 -0
- package/dist/view/normalize/normalize.js +42 -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 +39 -0
- package/dist/view/normalize/rules.js +120 -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/svg.d.ts +14 -0
- package/dist/view/normalize/svg.js +40 -0
- package/dist/view/normalize/svg.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 +55 -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 +65 -0
- package/dist/view/normalize/tree.js +235 -0
- package/dist/view/normalize/tree.js.map +1 -0
- package/dist/view/normalize/types.d.ts +146 -0
- package/dist/view/normalize/types.js +29 -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} +27 -36
- 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 +11 -0
- package/dist/view/prepare.js +63 -0
- package/dist/view/prepare.js.map +1 -0
- package/dist/view/registry.d.ts +78 -0
- package/dist/view/registry.js +27 -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 +83 -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 +286 -0
- package/dist/view/render/adopt.js.map +1 -0
- package/dist/view/render/attr-parts.d.ts +72 -0
- package/dist/view/render/attr-parts.js +262 -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 +173 -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/dispose.d.ts +3 -0
- package/dist/view/render/dispose.js +76 -0
- package/dist/view/render/dispose.js.map +1 -0
- package/dist/view/render/hook-part.d.ts +5 -0
- package/dist/view/render/hook-part.js +36 -0
- package/dist/view/render/hook-part.js.map +1 -0
- package/dist/view/render/hook-run.d.ts +2 -0
- package/dist/view/render/hook-run.js +72 -0
- package/dist/view/render/hook-run.js.map +1 -0
- package/dist/view/render/hooks.d.ts +108 -0
- package/dist/view/render/hooks.js +108 -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/keyed.d.ts +6 -0
- package/dist/view/render/keyed.js +15 -0
- package/dist/view/render/keyed.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 +55 -0
- package/dist/view/render/mismatch.js.map +1 -0
- package/dist/view/render/modal.d.ts +3 -0
- package/dist/view/render/modal.js +39 -0
- package/dist/view/render/modal.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 +21 -0
- package/dist/view/render/raw.js +72 -0
- package/dist/view/render/raw.js.map +1 -0
- package/dist/view/render/render.d.ts +15 -0
- package/dist/view/render/render.js +65 -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/toggles.d.ts +6 -0
- package/dist/view/render/toggles.js +6 -0
- package/dist/view/render/toggles.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 +28 -0
- package/dist/view/render/warn.js +114 -0
- package/dist/view/render/warn.js.map +1 -0
- package/dist/view/server/component.d.ts +12 -0
- package/dist/view/server/component.js +64 -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 +48 -0
- package/dist/view/server/index.js +80 -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 +68 -0
- package/dist/view/server/tags.js +132 -0
- package/dist/view/server/tags.js.map +1 -0
- package/dist/view/server/values.d.ts +18 -0
- package/dist/view/server/values.js +94 -0
- package/dist/view/server/values.js.map +1 -0
- package/dist/view/server/writer.d.ts +21 -0
- package/dist/view/server/writer.js +170 -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 +10 -0
- package/dist/view/template-element.js +45 -0
- package/dist/view/template-element.js.map +1 -0
- package/dist/view/template.d.ts +29 -0
- package/dist/view/template.js +84 -0
- package/dist/view/template.js.map +1 -0
- package/dist/view/trusted-html.d.ts +6 -0
- package/dist/view/trusted-html.js +34 -0
- package/dist/view/trusted-html.js.map +1 -0
- package/dist/vite.d.ts +57 -11
- package/dist/vite.js +319 -27
- package/dist/vite.js.map +1 -1
- package/package.json +70 -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/random.d.ts +0 -13
- package/dist/random.js +0 -19
- package/dist/random.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,132 @@
|
|
|
1
|
+
import { serverComponent, serverProvider, } from '../registry.js';
|
|
2
|
+
import { hookSpec } from '../render/hooks.js';
|
|
3
|
+
import { badHook } from '../render/warn.js';
|
|
4
|
+
import { escapeAttr, onlyWhitespace } from './escape.js';
|
|
5
|
+
import { absent, attrText, checkAttrName, lightChildrenError, multiText } from './values.js';
|
|
6
|
+
export const PLAIN = { k: 'plain' };
|
|
7
|
+
export class Markup {
|
|
8
|
+
/**
|
|
9
|
+
* `dev`: development markers and checks. `scope`: the nearest provider's scope, passed to
|
|
10
|
+
* components (undefined: the request's). `styles`: collects every `style` value written.
|
|
11
|
+
*/
|
|
12
|
+
constructor(dev, scope, styles) {
|
|
13
|
+
this.dev = dev;
|
|
14
|
+
this.scope = scope;
|
|
15
|
+
this.styles = styles;
|
|
16
|
+
this.buf = '';
|
|
17
|
+
this.items = [];
|
|
18
|
+
/** The template being written, for `styles` (its `loc` or id). */
|
|
19
|
+
this.where = '';
|
|
20
|
+
}
|
|
21
|
+
/** Records a `style` value the DOM will see (empty values declare nothing). */
|
|
22
|
+
style(value) {
|
|
23
|
+
if (value !== '' && this.styles !== undefined && !this.styles.has(value)) {
|
|
24
|
+
this.styles.set(value, this.where);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
write(markup) {
|
|
28
|
+
this.buf += markup;
|
|
29
|
+
}
|
|
30
|
+
/** The markup and deferred components written so far. */
|
|
31
|
+
done() {
|
|
32
|
+
this.flush();
|
|
33
|
+
return this.items;
|
|
34
|
+
}
|
|
35
|
+
flush() {
|
|
36
|
+
if (this.buf !== '')
|
|
37
|
+
this.items.push(this.buf);
|
|
38
|
+
this.buf = '';
|
|
39
|
+
}
|
|
40
|
+
/** `name=${v}` or `name="a ${v} b"`; returns the index of the next value. */
|
|
41
|
+
attr(s, values, at, opening) {
|
|
42
|
+
const { name, strings } = s;
|
|
43
|
+
const value = strings === undefined
|
|
44
|
+
? attrText(values[at], s, name, this.dev)
|
|
45
|
+
: multiText(values, at, strings, s, name, this.dev);
|
|
46
|
+
if (value !== null)
|
|
47
|
+
this.valued(name, value, opening);
|
|
48
|
+
return at + (strings === undefined ? 1 : strings.length - 1);
|
|
49
|
+
}
|
|
50
|
+
valued(name, value, opening) {
|
|
51
|
+
this.buf += ` ${name}="${escapeAttr(value)}"`;
|
|
52
|
+
if (name === 'style')
|
|
53
|
+
this.style(value);
|
|
54
|
+
if (opening !== undefined)
|
|
55
|
+
opening.attributes[name] = value;
|
|
56
|
+
}
|
|
57
|
+
/** A present boolean attribute (`?name`, or `true` from a hook's server half). */
|
|
58
|
+
bare(name, opening) {
|
|
59
|
+
this.buf += ` ${name}`;
|
|
60
|
+
if (opening !== undefined)
|
|
61
|
+
opening.attributes[name] = '';
|
|
62
|
+
}
|
|
63
|
+
/** An element hook: its server half's attributes (02 "Element hooks"). */
|
|
64
|
+
hook(v, opening) {
|
|
65
|
+
if (absent(v))
|
|
66
|
+
return;
|
|
67
|
+
const spec = hookSpec(v);
|
|
68
|
+
if (spec === undefined) {
|
|
69
|
+
if (this.dev)
|
|
70
|
+
badHook(v);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const attributes = spec.server?.(v.args) ?? {};
|
|
74
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
75
|
+
checkAttrName(name);
|
|
76
|
+
if (value === true)
|
|
77
|
+
this.bare(name, opening);
|
|
78
|
+
else
|
|
79
|
+
this.valued(name, value, opening);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** A custom element's start tag: a Gyral component, a provider, or a plain element. */
|
|
83
|
+
open(tag, html, attrs) {
|
|
84
|
+
this.buf += html;
|
|
85
|
+
const component = serverComponent(tag);
|
|
86
|
+
const provider = component === undefined ? serverProvider(tag) : undefined;
|
|
87
|
+
if (component === undefined && provider === undefined)
|
|
88
|
+
return undefined;
|
|
89
|
+
return { tag, component, provider, attributes: Object.fromEntries(attrs), properties: {} };
|
|
90
|
+
}
|
|
91
|
+
openEnd(opening) {
|
|
92
|
+
if (opening === undefined) {
|
|
93
|
+
this.buf += '>';
|
|
94
|
+
return PLAIN;
|
|
95
|
+
}
|
|
96
|
+
const { attributes, properties } = opening;
|
|
97
|
+
const messages = properties['initialMessages'];
|
|
98
|
+
const input = {
|
|
99
|
+
attributes,
|
|
100
|
+
properties,
|
|
101
|
+
initialMessages: Array.isArray(messages) ? messages : undefined,
|
|
102
|
+
scope: this.scope,
|
|
103
|
+
};
|
|
104
|
+
if (opening.provider !== undefined) {
|
|
105
|
+
const provided = opening.provider.open(input);
|
|
106
|
+
for (const [name, value] of Object.entries(provided.attributes)) {
|
|
107
|
+
this.buf += ` ${name}="${escapeAttr(value)}"`;
|
|
108
|
+
}
|
|
109
|
+
this.buf += '>';
|
|
110
|
+
const frame = { k: 'provider', outer: this.scope };
|
|
111
|
+
this.scope = provided.scope;
|
|
112
|
+
return frame;
|
|
113
|
+
}
|
|
114
|
+
const component = opening.component; // Sound: open() set one of the two.
|
|
115
|
+
this.flush();
|
|
116
|
+
this.items.push({ component, input });
|
|
117
|
+
return component.light ? { k: 'light', tag: opening.tag, items: this.items.length } : PLAIN;
|
|
118
|
+
}
|
|
119
|
+
close(frame, tag) {
|
|
120
|
+
if (frame.k === 'provider')
|
|
121
|
+
this.scope = frame.outer;
|
|
122
|
+
else if (frame.k === 'light') {
|
|
123
|
+
// Whitespace-only children are dropped; anything else is an error (ADR 0014).
|
|
124
|
+
if (this.items.length !== frame.items || !onlyWhitespace(this.buf)) {
|
|
125
|
+
lightChildrenError(frame.tag);
|
|
126
|
+
}
|
|
127
|
+
this.buf = '';
|
|
128
|
+
}
|
|
129
|
+
this.buf += `</${tag}>`;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=tags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tags.js","sourceRoot":"","sources":["../../../src/view/server/tags.ts"],"names":[],"mappings":"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","sourcesContent":["// Start tags and custom elements for the server renderer (view/06-server.md \"Writing a template\n// result\", \"Components\"): attribute, boolean and hook holes, and what a custom element's\n// `open`/`openEnd`/`close` segments do. A Gyral component's start tag is written here, but\n// its content (seed, shadow root, view) is deferred: the walk returns strings with the\n// deferred components between them, and `render` (index.ts) expands each one in its own step,\n// so every component boundary is a chunk boundary. A provider (`<gyral-stores>`) is a plain\n// element that gives its subtree a scope until its end tag.\nimport type { Segment } from '../normalize/types.js';\nimport {\n serverComponent,\n serverProvider,\n type ServerComponent,\n type ServerProvider,\n type ServerRenderInput,\n} from '../registry.js';\nimport { hookSpec, type HookResult } from '../render/hooks.js';\nimport { badHook } from '../render/warn.js';\nimport { escapeAttr, onlyWhitespace } from './escape.js';\nimport { absent, attrText, checkAttrName, lightChildrenError, multiText } from './values.js';\n\n/** A component whose content is written later, in its own render step. */\nexport interface Deferred {\n readonly component: ServerComponent;\n readonly input: ServerRenderInput;\n}\n\n/**\n * A render's `style` attribute values for a CSP (ADR 0020): each distinct value as the DOM sees\n * it (decoded), mapped to where it was first written (the template's `loc` or id; `''` when\n * neither is known).\n */\nexport type StyleValues = Map<string, string>;\n\n/** What a walk produces: markup, with deferred components in document order. */\nexport type Item = string | Deferred;\n\n/** A custom element's start tag while its attribute holes are written. */\nexport interface Opening {\n readonly tag: string;\n readonly component: ServerComponent | undefined;\n readonly provider: ServerProvider | undefined;\n readonly attributes: Record<string, string>;\n readonly properties: Record<string, unknown>;\n}\n\n/** An open custom element until its end tag: plain, a provider, or a light component. */\nexport type Frame =\n | { readonly k: 'plain' }\n | { readonly k: 'provider'; readonly outer: unknown }\n | { readonly k: 'light'; readonly tag: string; readonly items: number };\n\nexport const PLAIN: Frame = { k: 'plain' };\n\nexport class Markup {\n protected buf = '';\n protected readonly items: Item[] = [];\n\n /** The template being written, for `styles` (its `loc` or id). */\n protected where = '';\n\n /**\n * `dev`: development markers and checks. `scope`: the nearest provider's scope, passed to\n * components (undefined: the request's). `styles`: collects every `style` value written.\n */\n constructor(\n protected readonly dev: boolean,\n protected scope: unknown,\n protected readonly styles?: StyleValues,\n ) {}\n\n /** Records a `style` value the DOM will see (empty values declare nothing). */\n protected style(value: string): void {\n if (value !== '' && this.styles !== undefined && !this.styles.has(value)) {\n this.styles.set(value, this.where);\n }\n }\n\n write(markup: string): void {\n this.buf += markup;\n }\n\n /** The markup and deferred components written so far. */\n done(): Item[] {\n this.flush();\n return this.items;\n }\n\n private flush(): void {\n if (this.buf !== '') this.items.push(this.buf);\n this.buf = '';\n }\n\n /** `name=${v}` or `name=\"a ${v} b\"`; returns the index of the next value. */\n protected attr(\n s: Extract<Segment, { k: 'attr' }>,\n values: readonly unknown[],\n at: number,\n opening: Opening | undefined,\n ): number {\n const { name, strings } = s;\n const value =\n strings === undefined\n ? attrText(values[at], s, name, this.dev)\n : multiText(values, at, strings, s, name, this.dev);\n if (value !== null) this.valued(name, value, opening);\n return at + (strings === undefined ? 1 : strings.length - 1);\n }\n\n private valued(name: string, value: string, opening: Opening | undefined): void {\n this.buf += ` ${name}=\"${escapeAttr(value)}\"`;\n if (name === 'style') this.style(value);\n if (opening !== undefined) opening.attributes[name] = value;\n }\n\n /** A present boolean attribute (`?name`, or `true` from a hook's server half). */\n protected bare(name: string, opening: Opening | undefined): void {\n this.buf += ` ${name}`;\n if (opening !== undefined) opening.attributes[name] = '';\n }\n\n /** An element hook: its server half's attributes (02 \"Element hooks\"). */\n protected hook(v: unknown, opening: Opening | undefined): void {\n if (absent(v)) return;\n const spec = hookSpec(v);\n if (spec === undefined) {\n if (this.dev) badHook(v);\n return;\n }\n const attributes = spec.server?.((v as HookResult).args) ?? {};\n for (const [name, value] of Object.entries(attributes)) {\n checkAttrName(name);\n if (value === true) this.bare(name, opening);\n else this.valued(name, value, opening);\n }\n }\n\n /** A custom element's start tag: a Gyral component, a provider, or a plain element. */\n protected open(\n tag: string,\n html: string,\n attrs: readonly (readonly [string, string])[],\n ): Opening | undefined {\n this.buf += html;\n const component = serverComponent(tag);\n const provider = component === undefined ? serverProvider(tag) : undefined;\n if (component === undefined && provider === undefined) return undefined;\n return { tag, component, provider, attributes: Object.fromEntries(attrs), properties: {} };\n }\n\n protected openEnd(opening: Opening | undefined): Frame {\n if (opening === undefined) {\n this.buf += '>';\n return PLAIN;\n }\n const { attributes, properties } = opening;\n const messages = properties['initialMessages'];\n const input: ServerRenderInput = {\n attributes,\n properties,\n initialMessages: Array.isArray(messages) ? (messages as readonly unknown[]) : undefined,\n scope: this.scope,\n };\n if (opening.provider !== undefined) {\n const provided = opening.provider.open(input);\n for (const [name, value] of Object.entries(provided.attributes)) {\n this.buf += ` ${name}=\"${escapeAttr(value)}\"`;\n }\n this.buf += '>';\n const frame: Frame = { k: 'provider', outer: this.scope };\n this.scope = provided.scope;\n return frame;\n }\n const component = opening.component as ServerComponent; // Sound: open() set one of the two.\n this.flush();\n this.items.push({ component, input });\n return component.light ? { k: 'light', tag: opening.tag, items: this.items.length } : PLAIN;\n }\n\n protected close(frame: Frame, tag: string): void {\n if (frame.k === 'provider') this.scope = frame.outer;\n else if (frame.k === 'light') {\n // Whitespace-only children are dropped; anything else is an error (ADR 0014).\n if (this.items.length !== frame.items || !onlyWhitespace(this.buf)) {\n lightChildrenError(frame.tag);\n }\n this.buf = '';\n }\n this.buf += `</${tag}>`;\n }\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare const absent: (v: unknown) => boolean;
|
|
2
|
+
export declare const truthy: (v: unknown) => boolean;
|
|
3
|
+
/** A Promise in any hole: server renders are synchronous (06 "API"). Always an error. */
|
|
4
|
+
export declare function checkPromise(v: object, where: string): void;
|
|
5
|
+
/** `name=${v}`: the value to write, or null to leave the attribute out. */
|
|
6
|
+
export declare function attrText(v: unknown, at: object, name: string, dev: boolean): string | null;
|
|
7
|
+
/** `name="a ${x} b"`: pieces joined; `nothing` in any piece leaves the attribute out. */
|
|
8
|
+
export declare function multiText(values: readonly unknown[], from: number, strings: readonly string[], at: object, name: string, dev: boolean): string | null;
|
|
9
|
+
/** `<textarea>`/`<title>` content: child-hole rules flattened to a string, as on the client. */
|
|
10
|
+
export declare function textContent(v: unknown, at: object, dev: boolean): string;
|
|
11
|
+
/** Text written directly in table structure would be foster-parented (rule 7). */
|
|
12
|
+
export declare function fosterError(text: string, parent: string): never;
|
|
13
|
+
/** An svg template written outside SVG content (`parent`: its parent's name, if known). */
|
|
14
|
+
export declare function svgPlacementError(parent: string | undefined): never;
|
|
15
|
+
/** A light-DOM component owns its children (ADR 0014). */
|
|
16
|
+
export declare function lightChildrenError(tag: string): never;
|
|
17
|
+
/** An attribute name from a hook's server half must not break the start tag. */
|
|
18
|
+
export declare function checkAttrName(name: string): void;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Value rules for attribute and text-content holes on the server (view/02-bindings.md
|
|
2
|
+
// "Attribute values", "Live form state"; view/06-server.md "Writing a template result"),
|
|
3
|
+
// identical to the client's (render/attr-parts.ts) so both sides write the same attributes.
|
|
4
|
+
// And the server-only errors: a Promise anywhere (renders are synchronous), text the parser
|
|
5
|
+
// would move out of table structure, children given to a light-DOM component.
|
|
6
|
+
import { nothing } from '../render/values.js';
|
|
7
|
+
import { warnTrue, warnValue } from '../render/warn.js';
|
|
8
|
+
const SPEC = 'docs/design-docs/view';
|
|
9
|
+
export const absent = (v) => v === null || v === undefined || v === nothing;
|
|
10
|
+
export const truthy = (v) => v !== nothing && !!v;
|
|
11
|
+
const isObject = (v) => (typeof v === 'object' && v !== null) || typeof v === 'function';
|
|
12
|
+
/** `String(v)`: objects and functions as the client writes them (render/attr-parts.ts). */
|
|
13
|
+
const text = String;
|
|
14
|
+
const isThenable = (v) => typeof v.then === 'function';
|
|
15
|
+
/** A Promise in any hole: server renders are synchronous (06 "API"). Always an error. */
|
|
16
|
+
export function checkPromise(v, where) {
|
|
17
|
+
if (!isThenable(v))
|
|
18
|
+
return;
|
|
19
|
+
throw new TypeError(`gyral: ${where} got a Promise. Server renders are synchronous: state is known before ` +
|
|
20
|
+
'rendering, so load the data first (in the route handler or a form action) and pass ' +
|
|
21
|
+
`it as props (${SPEC}/06-server.md "API").`);
|
|
22
|
+
}
|
|
23
|
+
/** `String(v)` for an attribute value, with the development warning for objects. */
|
|
24
|
+
function written(v, at, name, dev) {
|
|
25
|
+
if (typeof v === 'string')
|
|
26
|
+
return v;
|
|
27
|
+
if (isObject(v)) {
|
|
28
|
+
checkPromise(v, `the attribute ${name}`);
|
|
29
|
+
if (dev)
|
|
30
|
+
warnValue(at, v, `the attribute ${name}`);
|
|
31
|
+
}
|
|
32
|
+
return text(v);
|
|
33
|
+
}
|
|
34
|
+
/** `name=${v}`: the value to write, or null to leave the attribute out. */
|
|
35
|
+
export function attrText(v, at, name, dev) {
|
|
36
|
+
return absent(v) ? null : written(v, at, name, dev);
|
|
37
|
+
}
|
|
38
|
+
/** `name="a ${x} b"`: pieces joined; `nothing` in any piece leaves the attribute out. */
|
|
39
|
+
export function multiText(values, from, strings, at, name, dev) {
|
|
40
|
+
let joined = strings[0] ?? '';
|
|
41
|
+
for (let i = 1; i < strings.length; i++) {
|
|
42
|
+
const v = values[from + i - 1];
|
|
43
|
+
if (v === nothing)
|
|
44
|
+
return null;
|
|
45
|
+
joined +=
|
|
46
|
+
(v === null || v === undefined ? '' : written(v, at, name, dev)) + strings[i];
|
|
47
|
+
}
|
|
48
|
+
return joined;
|
|
49
|
+
}
|
|
50
|
+
/** `<textarea>`/`<title>` content: child-hole rules flattened to a string, as on the client. */
|
|
51
|
+
export function textContent(v, at, dev) {
|
|
52
|
+
if (typeof v === 'string')
|
|
53
|
+
return v;
|
|
54
|
+
if (typeof v === 'number')
|
|
55
|
+
return String(v);
|
|
56
|
+
if (isObject(v)) {
|
|
57
|
+
checkPromise(v, 'the text content');
|
|
58
|
+
if (dev)
|
|
59
|
+
warnValue(at, v, 'the text content');
|
|
60
|
+
return text(v);
|
|
61
|
+
}
|
|
62
|
+
if (dev && v === true)
|
|
63
|
+
warnTrue(at);
|
|
64
|
+
return '';
|
|
65
|
+
}
|
|
66
|
+
/** Text written directly in table structure would be foster-parented (rule 7). */
|
|
67
|
+
export function fosterError(text, parent) {
|
|
68
|
+
throw new Error(`gyral: the text ${JSON.stringify(text.slice(0, 40))} is written directly inside ` +
|
|
69
|
+
`<${parent}>. The HTML parser moves text out of table structure (foster parenting), so ` +
|
|
70
|
+
'the page would differ from what the client renders. Put text inside a <td>, <th> or ' +
|
|
71
|
+
`<caption> (${SPEC}/09-template-rules.md, rule 7).`);
|
|
72
|
+
}
|
|
73
|
+
/** An svg template written outside SVG content (`parent`: its parent's name, if known). */
|
|
74
|
+
export function svgPlacementError(parent) {
|
|
75
|
+
throw new Error(`gyral: an svg template is written ${parent === undefined ? 'at the root of a view' : `inside <${parent}>`}, ` +
|
|
76
|
+
"which isn't SVG content, so the parser would not create SVG elements and the page " +
|
|
77
|
+
'would differ from what the client renders. Render svg`…` fragments inside an <svg> (or ' +
|
|
78
|
+
'another SVG element, not <foreignObject>) of an html template, or write the whole ' +
|
|
79
|
+
`graphic with html (${SPEC}/01-templates.md "svg templates").`);
|
|
80
|
+
}
|
|
81
|
+
/** A light-DOM component owns its children (ADR 0014). */
|
|
82
|
+
export function lightChildrenError(tag) {
|
|
83
|
+
throw new Error(`gyral: <${tag}> renders in light DOM (shadow: false), so it owns its children, but its ` +
|
|
84
|
+
'parent wrote children inside it. Pass the data as props instead, or make it a shadow ' +
|
|
85
|
+
`component and use <slot> (${SPEC}/06-server.md "Components", ADR 0014).`);
|
|
86
|
+
}
|
|
87
|
+
/** An attribute name from a hook's server half must not break the start tag. */
|
|
88
|
+
export function checkAttrName(name) {
|
|
89
|
+
if (/^[^\s"'>/=\0]+$/.test(name))
|
|
90
|
+
return;
|
|
91
|
+
throw new TypeError(`gyral: an element hook's server half returned the attribute name ${JSON.stringify(name)}, ` +
|
|
92
|
+
`which isn't a valid attribute name (${SPEC}/02-bindings.md "Element hooks").`);
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.js","sourceRoot":"","sources":["../../../src/view/server/values.ts"],"names":[],"mappings":"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","sourcesContent":["// Value rules for attribute and text-content holes on the server (view/02-bindings.md\n// \"Attribute values\", \"Live form state\"; view/06-server.md \"Writing a template result\"),\n// identical to the client's (render/attr-parts.ts) so both sides write the same attributes.\n// And the server-only errors: a Promise anywhere (renders are synchronous), text the parser\n// would move out of table structure, children given to a light-DOM component.\nimport { nothing } from '../render/values.js';\nimport { warnTrue, warnValue } from '../render/warn.js';\n\nconst SPEC = 'docs/design-docs/view';\n\nexport const absent = (v: unknown): boolean => v === null || v === undefined || v === nothing;\nexport const truthy = (v: unknown): boolean => v !== nothing && !!v;\n\nconst isObject = (v: unknown): v is object =>\n (typeof v === 'object' && v !== null) || typeof v === 'function';\n\n/** `String(v)`: objects and functions as the client writes them (render/attr-parts.ts). */\nconst text = String as (value: unknown) => string;\n\nconst isThenable = (v: object): boolean =>\n typeof (v as { readonly then?: unknown }).then === 'function';\n\n/** A Promise in any hole: server renders are synchronous (06 \"API\"). Always an error. */\nexport function checkPromise(v: object, where: string): void {\n if (!isThenable(v)) return;\n throw new TypeError(\n `gyral: ${where} got a Promise. Server renders are synchronous: state is known before ` +\n 'rendering, so load the data first (in the route handler or a form action) and pass ' +\n `it as props (${SPEC}/06-server.md \"API\").`,\n );\n}\n\n/** `String(v)` for an attribute value, with the development warning for objects. */\nfunction written(v: unknown, at: object, name: string, dev: boolean): string {\n if (typeof v === 'string') return v;\n if (isObject(v)) {\n checkPromise(v, `the attribute ${name}`);\n if (dev) warnValue(at, v, `the attribute ${name}`);\n }\n return text(v);\n}\n\n/** `name=${v}`: the value to write, or null to leave the attribute out. */\nexport function attrText(v: unknown, at: object, name: string, dev: boolean): string | null {\n return absent(v) ? null : written(v, at, name, dev);\n}\n\n/** `name=\"a ${x} b\"`: pieces joined; `nothing` in any piece leaves the attribute out. */\nexport function multiText(\n values: readonly unknown[],\n from: number,\n strings: readonly string[],\n at: object,\n name: string,\n dev: boolean,\n): string | null {\n let joined = strings[0] ?? '';\n for (let i = 1; i < strings.length; i++) {\n const v = values[from + i - 1];\n if (v === nothing) return null;\n joined +=\n (v === null || v === undefined ? '' : written(v, at, name, dev)) + (strings[i] as string);\n }\n return joined;\n}\n\n/** `<textarea>`/`<title>` content: child-hole rules flattened to a string, as on the client. */\nexport function textContent(v: unknown, at: object, dev: boolean): string {\n if (typeof v === 'string') return v;\n if (typeof v === 'number') return String(v);\n if (isObject(v)) {\n checkPromise(v, 'the text content');\n if (dev) warnValue(at, v, 'the text content');\n return text(v);\n }\n if (dev && v === true) warnTrue(at);\n return '';\n}\n\n/** Text written directly in table structure would be foster-parented (rule 7). */\nexport function fosterError(text: string, parent: string): never {\n throw new Error(\n `gyral: the text ${JSON.stringify(text.slice(0, 40))} is written directly inside ` +\n `<${parent}>. The HTML parser moves text out of table structure (foster parenting), so ` +\n 'the page would differ from what the client renders. Put text inside a <td>, <th> or ' +\n `<caption> (${SPEC}/09-template-rules.md, rule 7).`,\n );\n}\n\n/** An svg template written outside SVG content (`parent`: its parent's name, if known). */\nexport function svgPlacementError(parent: string | undefined): never {\n throw new Error(\n `gyral: an svg template is written ${parent === undefined ? 'at the root of a view' : `inside <${parent}>`}, ` +\n \"which isn't SVG content, so the parser would not create SVG elements and the page \" +\n 'would differ from what the client renders. Render svg`…` fragments inside an <svg> (or ' +\n 'another SVG element, not <foreignObject>) of an html template, or write the whole ' +\n `graphic with html (${SPEC}/01-templates.md \"svg templates\").`,\n );\n}\n\n/** A light-DOM component owns its children (ADR 0014). */\nexport function lightChildrenError(tag: string): never {\n throw new Error(\n `gyral: <${tag}> renders in light DOM (shadow: false), so it owns its children, but its ` +\n 'parent wrote children inside it. Pass the data as props instead, or make it a shadow ' +\n `component and use <slot> (${SPEC}/06-server.md \"Components\", ADR 0014).`,\n );\n}\n\n/** An attribute name from a hook's server half must not break the start tag. */\nexport function checkAttrName(name: string): void {\n if (/^[^\\s\"'>/=\\0]+$/.test(name)) return;\n throw new TypeError(\n `gyral: an element hook's server half returned the attribute name ${JSON.stringify(name)}, ` +\n `which isn't a valid attribute name (${SPEC}/02-bindings.md \"Element hooks\").`,\n );\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type TemplateResult } from '../template.js';
|
|
2
|
+
import { Markup } from './tags.js';
|
|
3
|
+
export type { Deferred, Item, StyleValues } from './tags.js';
|
|
4
|
+
/**
|
|
5
|
+
* What a child hole's parent means for its value (the development checks): a table tag (text
|
|
6
|
+
* would be foster-parented), SVG content (where svg templates may render), or nothing.
|
|
7
|
+
*/
|
|
8
|
+
type Ctx = string | undefined;
|
|
9
|
+
/** Warning key for values outside any template (the render root, a component's view). */
|
|
10
|
+
export declare const ROOT: object;
|
|
11
|
+
export declare class Writer extends Markup {
|
|
12
|
+
/** Writing a page shell's holes (a `server` template): never hydrated, so no anchors (06). */
|
|
13
|
+
private shell;
|
|
14
|
+
/** A child value (02 "Child values"). `ctx`: what its parent is (`Ctx`). */
|
|
15
|
+
child(v: unknown, ctx: Ctx, at: object): void;
|
|
16
|
+
private object;
|
|
17
|
+
/** `each(…)`: rows one after another, no markers (03). Keys are checked in development. */
|
|
18
|
+
private list;
|
|
19
|
+
/** One template instance: its segments with this render's values. */
|
|
20
|
+
template(result: TemplateResult, ctx: Ctx): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// The server renderer's walk (view/06-server.md "Writing a template result"): writes a child
|
|
2
|
+
// value by walking template objects' `segments` (01), never tokenizing or building a DOM. Each
|
|
3
|
+
// string segment is written verbatim; each hole op takes its value(s). Start tags and custom
|
|
4
|
+
// elements are tags.ts.
|
|
5
|
+
import { isList, nothing, rawHtml } from '../render/values.js';
|
|
6
|
+
import { badChild, badKey, warnTrue } from '../render/warn.js';
|
|
7
|
+
import { isTemplateResult, templateOf } from '../template.js';
|
|
8
|
+
import { escapeText, onlyWhitespace } from './escape.js';
|
|
9
|
+
import { Markup, PLAIN } from './tags.js';
|
|
10
|
+
import { checkPromise, fosterError, svgPlacementError, textContent, truthy } from './values.js';
|
|
11
|
+
/** Parents in which the parser moves non-whitespace text out (foster parenting). */
|
|
12
|
+
const TABLE = new Set(['table', 'tbody', 'thead', 'tfoot', 'tr']);
|
|
13
|
+
const SVG = '#svg';
|
|
14
|
+
const isTable = (ctx) => ctx !== undefined && TABLE.has(ctx);
|
|
15
|
+
/** A child op's context: its parent's, or the enclosing one at the template root. */
|
|
16
|
+
const ctxOf = (s, outer) => s.svg ? SVG : s.in === undefined ? outer : s.in;
|
|
17
|
+
/** Warning key for values outside any template (the render root, a component's view). */
|
|
18
|
+
export const ROOT = {};
|
|
19
|
+
export class Writer extends Markup {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(...arguments);
|
|
22
|
+
/** Writing a page shell's holes (a `server` template): never hydrated, so no anchors (06). */
|
|
23
|
+
this.shell = false;
|
|
24
|
+
}
|
|
25
|
+
/** A child value (02 "Child values"). `ctx`: what its parent is (`Ctx`). */
|
|
26
|
+
child(v, ctx, at) {
|
|
27
|
+
switch (typeof v) {
|
|
28
|
+
case 'string':
|
|
29
|
+
if (v === '')
|
|
30
|
+
return;
|
|
31
|
+
if (this.dev && isTable(ctx) && !onlyWhitespace(v))
|
|
32
|
+
fosterError(v, ctx);
|
|
33
|
+
this.buf += escapeText(v);
|
|
34
|
+
return;
|
|
35
|
+
case 'number':
|
|
36
|
+
if (this.dev && isTable(ctx))
|
|
37
|
+
fosterError(String(v), ctx);
|
|
38
|
+
this.buf += String(v);
|
|
39
|
+
return;
|
|
40
|
+
case 'object':
|
|
41
|
+
if (v !== null)
|
|
42
|
+
this.object(v, ctx, at);
|
|
43
|
+
return;
|
|
44
|
+
case 'boolean':
|
|
45
|
+
if (v && this.dev)
|
|
46
|
+
warnTrue(at);
|
|
47
|
+
return;
|
|
48
|
+
case 'undefined':
|
|
49
|
+
return;
|
|
50
|
+
default:
|
|
51
|
+
if (v !== nothing && this.dev)
|
|
52
|
+
badChild(v);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
object(v, ctx, at) {
|
|
56
|
+
if (isTemplateResult(v)) {
|
|
57
|
+
this.template(v, ctx);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (isList(v)) {
|
|
61
|
+
this.list(v, ctx, at);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (Array.isArray(v)) {
|
|
65
|
+
for (const item of v)
|
|
66
|
+
this.child(item, ctx, at);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const raw = rawHtml(v);
|
|
70
|
+
if (raw !== undefined) {
|
|
71
|
+
// The start anchor hydration finds (02 "raw(html)"); a page shell is never hydrated.
|
|
72
|
+
this.buf += this.shell ? raw : `<!---->${raw}`;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
checkPromise(v, 'a child hole');
|
|
76
|
+
if (this.dev)
|
|
77
|
+
badChild(v);
|
|
78
|
+
}
|
|
79
|
+
/** `each(…)`: rows one after another, no markers (03). Keys are checked in development. */
|
|
80
|
+
list(v, ctx, at) {
|
|
81
|
+
const { items, key, row, pick } = v;
|
|
82
|
+
const seen = this.dev ? new Set() : undefined;
|
|
83
|
+
for (let i = 0; i < items.length; i++) {
|
|
84
|
+
const item = items[i];
|
|
85
|
+
if (seen !== undefined) {
|
|
86
|
+
const k = key(item);
|
|
87
|
+
const dup = seen.has(k);
|
|
88
|
+
if (dup || (typeof k !== 'string' && typeof k !== 'number'))
|
|
89
|
+
badKey(k, i, dup);
|
|
90
|
+
seen.add(k);
|
|
91
|
+
}
|
|
92
|
+
this.child(row(item, pick === undefined ? undefined : pick(item)), ctx, at);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** One template instance: its segments with this render's values. */
|
|
96
|
+
template(result, ctx) {
|
|
97
|
+
const template = templateOf(result);
|
|
98
|
+
const segments = template.segments;
|
|
99
|
+
if (segments === undefined) {
|
|
100
|
+
throw new Error(`gyral: template ${JSON.stringify(template.html.slice(0, 40))} has no server ` +
|
|
101
|
+
'segments: it was compiled for the client. Render on the server with an SSR build ' +
|
|
102
|
+
'(or the runtime normalizer), which keeps them ' +
|
|
103
|
+
'(docs/design-docs/view/01-templates.md "Compiled").');
|
|
104
|
+
}
|
|
105
|
+
// An svg template is SVG content: the parser creates SVG elements only inside SVG (01).
|
|
106
|
+
if (this.dev && template.svg && ctx !== SVG)
|
|
107
|
+
svgPlacementError(ctx);
|
|
108
|
+
// Development marker: hydration checks the id before each instance (07). Page shells are
|
|
109
|
+
// never hydrated.
|
|
110
|
+
if (this.dev && !template.server)
|
|
111
|
+
this.buf += `<!--gyral:${template.id ?? ''}-->`;
|
|
112
|
+
const values = result.values;
|
|
113
|
+
const outer = this.shell;
|
|
114
|
+
const outerWhere = this.where;
|
|
115
|
+
this.shell = template.server === true;
|
|
116
|
+
if (this.styles !== undefined) {
|
|
117
|
+
this.where = template.loc ?? template.id ?? '';
|
|
118
|
+
for (const css of template.staticStyles ?? [])
|
|
119
|
+
this.style(css);
|
|
120
|
+
}
|
|
121
|
+
let at = 0;
|
|
122
|
+
let opening;
|
|
123
|
+
let frames;
|
|
124
|
+
for (const s of segments) {
|
|
125
|
+
if (typeof s === 'string') {
|
|
126
|
+
this.buf += s;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
switch (s.k) {
|
|
130
|
+
case 'child':
|
|
131
|
+
this.child(values[at++], ctxOf(s, ctx), s);
|
|
132
|
+
break;
|
|
133
|
+
case 'text':
|
|
134
|
+
this.buf += escapeText(textContent(values[at++], s, this.dev));
|
|
135
|
+
break;
|
|
136
|
+
case 'attr':
|
|
137
|
+
at = this.attr(s, values, at, opening);
|
|
138
|
+
break;
|
|
139
|
+
case 'bool':
|
|
140
|
+
// `?indeterminate` has no attribute: it is the property only (02 "Live form state").
|
|
141
|
+
// `?modal`/`?popover-open` neither: the browser opens them after hydration (02).
|
|
142
|
+
if (truthy(values[at]) && !/^(indeterminate|modal|popover-open)$/.test(s.name)) {
|
|
143
|
+
this.bare(s.name, opening);
|
|
144
|
+
}
|
|
145
|
+
at++;
|
|
146
|
+
break;
|
|
147
|
+
case 'prop':
|
|
148
|
+
if (opening !== undefined)
|
|
149
|
+
opening.properties[s.name] = values[at];
|
|
150
|
+
at++;
|
|
151
|
+
break;
|
|
152
|
+
case 'hook':
|
|
153
|
+
this.hook(values[at++], opening);
|
|
154
|
+
break;
|
|
155
|
+
case 'open':
|
|
156
|
+
opening = this.open(s.tag, s.html, s.attrs);
|
|
157
|
+
break;
|
|
158
|
+
case 'openEnd':
|
|
159
|
+
(frames ??= []).push(this.openEnd(opening));
|
|
160
|
+
opening = undefined;
|
|
161
|
+
break;
|
|
162
|
+
case 'close':
|
|
163
|
+
this.close(frames?.pop() ?? PLAIN, s.tag);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
this.shell = outer;
|
|
167
|
+
this.where = outerWhere;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/view/server/writer.ts"],"names":[],"mappings":"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","sourcesContent":["// The server renderer's walk (view/06-server.md \"Writing a template result\"): writes a child\n// value by walking template objects' `segments` (01), never tokenizing or building a DOM. Each\n// string segment is written verbatim; each hole op takes its value(s). Start tags and custom\n// elements are tags.ts.\nimport { isList, nothing, rawHtml, type ListResult } from '../render/values.js';\nimport { badChild, badKey, warnTrue } from '../render/warn.js';\nimport { isTemplateResult, templateOf, type TemplateResult } from '../template.js';\nimport { escapeText, onlyWhitespace } from './escape.js';\nimport { Markup, PLAIN, type Frame, type Opening } from './tags.js';\nimport { checkPromise, fosterError, svgPlacementError, textContent, truthy } from './values.js';\n\nexport type { Deferred, Item, StyleValues } from './tags.js';\n\n/** Parents in which the parser moves non-whitespace text out (foster parenting). */\nconst TABLE = new Set(['table', 'tbody', 'thead', 'tfoot', 'tr']);\n\n/**\n * What a child hole's parent means for its value (the development checks): a table tag (text\n * would be foster-parented), SVG content (where svg templates may render), or nothing.\n */\ntype Ctx = string | undefined;\nconst SVG: Ctx = '#svg';\n\nconst isTable = (ctx: Ctx): ctx is string => ctx !== undefined && TABLE.has(ctx);\n\n/** A child op's context: its parent's, or the enclosing one at the template root. */\nconst ctxOf = (s: { readonly in?: string; readonly svg?: true }, outer: Ctx): Ctx =>\n s.svg ? SVG : s.in === undefined ? outer : s.in;\n\n/** Warning key for values outside any template (the render root, a component's view). */\nexport const ROOT: object = {};\n\nexport class Writer extends Markup {\n /** Writing a page shell's holes (a `server` template): never hydrated, so no anchors (06). */\n private shell = false;\n\n /** A child value (02 \"Child values\"). `ctx`: what its parent is (`Ctx`). */\n child(v: unknown, ctx: Ctx, at: object): void {\n switch (typeof v) {\n case 'string':\n if (v === '') return;\n if (this.dev && isTable(ctx) && !onlyWhitespace(v)) fosterError(v, ctx);\n this.buf += escapeText(v);\n return;\n case 'number':\n if (this.dev && isTable(ctx)) fosterError(String(v), ctx);\n this.buf += String(v);\n return;\n case 'object':\n if (v !== null) this.object(v, ctx, at);\n return;\n case 'boolean':\n if (v && this.dev) warnTrue(at);\n return;\n case 'undefined':\n return;\n default:\n if (v !== nothing && this.dev) badChild(v);\n }\n }\n\n private object(v: object, ctx: Ctx, at: object): void {\n if (isTemplateResult(v)) {\n this.template(v, ctx);\n return;\n }\n if (isList(v)) {\n this.list(v, ctx, at);\n return;\n }\n if (Array.isArray(v)) {\n for (const item of v as readonly unknown[]) this.child(item, ctx, at);\n return;\n }\n const raw = rawHtml(v);\n if (raw !== undefined) {\n // The start anchor hydration finds (02 \"raw(html)\"); a page shell is never hydrated.\n this.buf += this.shell ? raw : `<!---->${raw}`;\n return;\n }\n checkPromise(v, 'a child hole');\n if (this.dev) badChild(v);\n }\n\n /** `each(…)`: rows one after another, no markers (03). Keys are checked in development. */\n private list(v: ListResult, ctx: Ctx, at: object): void {\n const { items, key, row, pick } = v;\n const seen = this.dev ? new Set<unknown>() : undefined;\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (seen !== undefined) {\n const k = key(item);\n const dup = seen.has(k);\n if (dup || (typeof k !== 'string' && typeof k !== 'number')) badKey(k, i, dup);\n seen.add(k);\n }\n this.child(row(item, pick === undefined ? undefined : pick(item)), ctx, at);\n }\n }\n\n /** One template instance: its segments with this render's values. */\n template(result: TemplateResult, ctx: Ctx): void {\n const template = templateOf(result);\n const segments = template.segments;\n if (segments === undefined) {\n throw new Error(\n `gyral: template ${JSON.stringify(template.html.slice(0, 40))} has no server ` +\n 'segments: it was compiled for the client. Render on the server with an SSR build ' +\n '(or the runtime normalizer), which keeps them ' +\n '(docs/design-docs/view/01-templates.md \"Compiled\").',\n );\n }\n // An svg template is SVG content: the parser creates SVG elements only inside SVG (01).\n if (this.dev && template.svg && ctx !== SVG) svgPlacementError(ctx);\n // Development marker: hydration checks the id before each instance (07). Page shells are\n // never hydrated.\n if (this.dev && !template.server) this.buf += `<!--gyral:${template.id ?? ''}-->`;\n const values = result.values;\n const outer = this.shell;\n const outerWhere = this.where;\n this.shell = template.server === true;\n if (this.styles !== undefined) {\n this.where = template.loc ?? template.id ?? '';\n for (const css of template.staticStyles ?? []) this.style(css);\n }\n let at = 0;\n let opening: Opening | undefined;\n let frames: Frame[] | undefined;\n for (const s of segments) {\n if (typeof s === 'string') {\n this.buf += s;\n continue;\n }\n switch (s.k) {\n case 'child':\n this.child(values[at++], ctxOf(s, ctx), s);\n break;\n case 'text':\n this.buf += escapeText(textContent(values[at++], s, this.dev));\n break;\n case 'attr':\n at = this.attr(s, values, at, opening);\n break;\n case 'bool':\n // `?indeterminate` has no attribute: it is the property only (02 \"Live form state\").\n // `?modal`/`?popover-open` neither: the browser opens them after hydration (02).\n if (truthy(values[at]) && !/^(indeterminate|modal|popover-open)$/.test(s.name)) {\n this.bare(s.name, opening);\n }\n at++;\n break;\n case 'prop':\n if (opening !== undefined) opening.properties[s.name] = values[at];\n at++;\n break;\n case 'hook':\n this.hook(values[at++], opening);\n break;\n case 'open':\n opening = this.open(s.tag, s.html, s.attrs);\n break;\n case 'openEnd':\n (frames ??= []).push(this.openEnd(opening));\n opening = undefined;\n break;\n case 'close':\n this.close(frames?.pop() ?? PLAIN, s.tag);\n }\n }\n this.shell = outer;\n this.where = outerWhere;\n }\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const STYLE: unique symbol;
|
|
2
|
+
/** What `css` returns: CSS text, mapped to one shared `CSSStyleSheet` in the browser. */
|
|
3
|
+
export interface StyleSource {
|
|
4
|
+
readonly [STYLE]: true;
|
|
5
|
+
readonly text: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* What `spec.styles` accepts: `css` values, plain CSS strings (e.g.
|
|
9
|
+
* `import base from './base.css?inline'`) and arrays of them, nested freely. CSS is trusted
|
|
10
|
+
* author code: never interpolate user input.
|
|
11
|
+
*/
|
|
12
|
+
export type Styles = StyleSource | string | readonly Styles[];
|
|
13
|
+
/** A `css` interpolation: inserted as written (another `css` value inserts its text). */
|
|
14
|
+
export type CssValue = string | number | StyleSource;
|
|
15
|
+
export declare const isStyleSource: (value: unknown) => value is StyleSource;
|
|
16
|
+
/**
|
|
17
|
+
* Component CSS: `` css`p { margin-block: ${GAP}px; }` ``. Strings and numbers are inserted as
|
|
18
|
+
* written, so values from your own constants need no wrapper.
|
|
19
|
+
*/
|
|
20
|
+
export declare function css(strings: TemplateStringsArray, ...values: readonly CssValue[]): StyleSource;
|
|
21
|
+
/** The CSS texts of `styles`, flattened in order (the server writes them, 06). */
|
|
22
|
+
export declare function styleTexts(styles: Styles | undefined): string[];
|
|
23
|
+
/** One shared sheet per style source (or per distinct string), created on first use. */
|
|
24
|
+
export declare function sheetsFor(styles: Styles | undefined): CSSStyleSheet[];
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Component styles (view/08-styles.md "Authoring", "Browser"): the `css` tag and the shared
|
|
2
|
+
// sheets. A style source is CSS text plus a cache slot for its one `CSSStyleSheet`, created on
|
|
3
|
+
// first use with `replaceSync`; components that share a source share the sheet. Plain strings
|
|
4
|
+
// are style sources too (cached by text). The server reads the text (06), never the sheet.
|
|
5
|
+
const STYLE = Symbol('gyral.css');
|
|
6
|
+
export const isStyleSource = (value) => typeof value === 'object' && value !== null && STYLE in value;
|
|
7
|
+
/**
|
|
8
|
+
* Component CSS: `` css`p { margin-block: ${GAP}px; }` ``. Strings and numbers are inserted as
|
|
9
|
+
* written, so values from your own constants need no wrapper.
|
|
10
|
+
*/
|
|
11
|
+
export function css(strings, ...values) {
|
|
12
|
+
let text = strings[0] ?? '';
|
|
13
|
+
for (let i = 0; i < values.length; i++) {
|
|
14
|
+
const v = values[i];
|
|
15
|
+
text += (isStyleSource(v) ? v.text : String(v)) + (strings[i + 1] ?? '');
|
|
16
|
+
}
|
|
17
|
+
return { [STYLE]: true, text };
|
|
18
|
+
}
|
|
19
|
+
/** The CSS texts of `styles`, flattened in order (the server writes them, 06). */
|
|
20
|
+
export function styleTexts(styles) {
|
|
21
|
+
if (styles === undefined)
|
|
22
|
+
return [];
|
|
23
|
+
if (typeof styles === 'string')
|
|
24
|
+
return [styles];
|
|
25
|
+
if (isStyleSource(styles))
|
|
26
|
+
return [styles.text];
|
|
27
|
+
return styles.flatMap(styleTexts);
|
|
28
|
+
}
|
|
29
|
+
const bySource = new WeakMap();
|
|
30
|
+
const byText = new Map();
|
|
31
|
+
function sheetOf(text) {
|
|
32
|
+
const sheet = new CSSStyleSheet();
|
|
33
|
+
sheet.replaceSync(text);
|
|
34
|
+
return sheet;
|
|
35
|
+
}
|
|
36
|
+
/** One shared sheet per style source (or per distinct string), created on first use. */
|
|
37
|
+
export function sheetsFor(styles) {
|
|
38
|
+
if (styles === undefined)
|
|
39
|
+
return [];
|
|
40
|
+
if (typeof styles === 'string') {
|
|
41
|
+
let sheet = byText.get(styles);
|
|
42
|
+
if (sheet === undefined) {
|
|
43
|
+
sheet = sheetOf(styles);
|
|
44
|
+
byText.set(styles, sheet);
|
|
45
|
+
}
|
|
46
|
+
return [sheet];
|
|
47
|
+
}
|
|
48
|
+
if (isStyleSource(styles)) {
|
|
49
|
+
let sheet = bySource.get(styles);
|
|
50
|
+
if (sheet === undefined) {
|
|
51
|
+
sheet = sheetOf(styles.text);
|
|
52
|
+
bySource.set(styles, sheet);
|
|
53
|
+
}
|
|
54
|
+
return [sheet];
|
|
55
|
+
}
|
|
56
|
+
return styles.flatMap(sheetsFor);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/view/styles.ts"],"names":[],"mappings":"AAAA,4FAA4F;AAC5F,+FAA+F;AAC/F,8FAA8F;AAC9F,2FAA2F;AAE3F,MAAM,KAAK,GAAkB,MAAM,CAAC,WAAW,CAAC,CAAC;AAkBjD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAc,EAAwB,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC;AAEhE;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,OAA6B,EAAE,GAAG,MAA2B;IAC/E,IAAI,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,UAAU,CAAC,MAA0B;IACnD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACpC,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAChD,IAAI,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,QAAQ,GAAG,IAAI,OAAO,EAA8B,CAAC;AAC3D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEhD,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAClC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACxB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,SAAS,CAAC,MAA0B;IAClD,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACpC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,IAAI,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC7B,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC","sourcesContent":["// Component styles (view/08-styles.md \"Authoring\", \"Browser\"): the `css` tag and the shared\n// sheets. A style source is CSS text plus a cache slot for its one `CSSStyleSheet`, created on\n// first use with `replaceSync`; components that share a source share the sheet. Plain strings\n// are style sources too (cached by text). The server reads the text (06), never the sheet.\n\nconst STYLE: unique symbol = Symbol('gyral.css');\n\n/** What `css` returns: CSS text, mapped to one shared `CSSStyleSheet` in the browser. */\nexport interface StyleSource {\n readonly [STYLE]: true;\n readonly text: string;\n}\n\n/**\n * What `spec.styles` accepts: `css` values, plain CSS strings (e.g.\n * `import base from './base.css?inline'`) and arrays of them, nested freely. CSS is trusted\n * author code: never interpolate user input.\n */\nexport type Styles = StyleSource | string | readonly Styles[];\n\n/** A `css` interpolation: inserted as written (another `css` value inserts its text). */\nexport type CssValue = string | number | StyleSource;\n\nexport const isStyleSource = (value: unknown): value is StyleSource =>\n typeof value === 'object' && value !== null && STYLE in value;\n\n/**\n * Component CSS: `` css`p { margin-block: ${GAP}px; }` ``. Strings and numbers are inserted as\n * written, so values from your own constants need no wrapper.\n */\nexport function css(strings: TemplateStringsArray, ...values: readonly CssValue[]): StyleSource {\n let text = strings[0] ?? '';\n for (let i = 0; i < values.length; i++) {\n const v = values[i];\n text += (isStyleSource(v) ? v.text : String(v)) + (strings[i + 1] ?? '');\n }\n return { [STYLE]: true, text };\n}\n\n/** The CSS texts of `styles`, flattened in order (the server writes them, 06). */\nexport function styleTexts(styles: Styles | undefined): string[] {\n if (styles === undefined) return [];\n if (typeof styles === 'string') return [styles];\n if (isStyleSource(styles)) return [styles.text];\n return styles.flatMap(styleTexts);\n}\n\nconst bySource = new WeakMap<StyleSource, CSSStyleSheet>();\nconst byText = new Map<string, CSSStyleSheet>();\n\nfunction sheetOf(text: string): CSSStyleSheet {\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(text);\n return sheet;\n}\n\n/** One shared sheet per style source (or per distinct string), created on first use. */\nexport function sheetsFor(styles: Styles | undefined): CSSStyleSheet[] {\n if (styles === undefined) return [];\n if (typeof styles === 'string') {\n let sheet = byText.get(styles);\n if (sheet === undefined) {\n sheet = sheetOf(styles);\n byText.set(styles, sheet);\n }\n return [sheet];\n }\n if (isStyleSource(styles)) {\n let sheet = bySource.get(styles);\n if (sheet === undefined) {\n sheet = sheetOf(styles.text);\n bySource.set(styles, sheet);\n }\n return [sheet];\n }\n return styles.flatMap(sheetsFor);\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { TemplateObject } from './normalize/types.js';
|
|
2
|
+
/** The cached <template> element for `template`, parsed (and checked) on first use. */
|
|
3
|
+
export declare function templateElement(template: TemplateObject): HTMLTemplateElement;
|
|
4
|
+
/**
|
|
5
|
+
* Prepares an svg template's <template> element (01 "svg templates"): its HTML is parsed inside
|
|
6
|
+
* an <svg>, so the parser creates SVG elements (camelCase names and attributes, namespaced
|
|
7
|
+
* static attributes), and that <svg>'s children become the content. Called with every svg
|
|
8
|
+
* result, before anything renders it; outside a document (the server) there is nothing to do.
|
|
9
|
+
*/
|
|
10
|
+
export declare function svgTemplate(template: TemplateObject): void;
|