@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,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modules statically retained by the app's inputs (transitively). A component among them is
|
|
3
|
+
* defined at startup by the app's own entry; giving it to the loader as well would make the
|
|
4
|
+
* bundler split it out of the entry into a chunk of its own.
|
|
5
|
+
*/
|
|
6
|
+
export async function staticallyReachable(ctx, inputs) {
|
|
7
|
+
const seen = new Set();
|
|
8
|
+
const reachable = new Set();
|
|
9
|
+
const entries = new Set();
|
|
10
|
+
const queue = [];
|
|
11
|
+
for (const input of inputs) {
|
|
12
|
+
const resolved = await ctx.resolve(input, undefined, { isEntry: true });
|
|
13
|
+
if (resolved !== null && !resolved.external) {
|
|
14
|
+
entries.add(resolved.id);
|
|
15
|
+
queue.push(resolved);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
while (queue.length > 0) {
|
|
19
|
+
const resolved = queue.pop();
|
|
20
|
+
if (resolved === undefined)
|
|
21
|
+
break;
|
|
22
|
+
const { id } = resolved;
|
|
23
|
+
if (seen.has(id) || id === '\0virtual:gyral/components')
|
|
24
|
+
continue;
|
|
25
|
+
seen.add(id);
|
|
26
|
+
const info = await ctx.load({ ...resolved, resolveDependencies: true });
|
|
27
|
+
// A side-effect-only import can be dropped by tree shaking. Keep such components in
|
|
28
|
+
// the loader rather than assuming the entry registered them (including through barrels).
|
|
29
|
+
if ((info.moduleSideEffects ?? resolved.moduleSideEffects) === false && !entries.has(id))
|
|
30
|
+
continue;
|
|
31
|
+
reachable.add(id);
|
|
32
|
+
for (const next of info.importedIds) {
|
|
33
|
+
if (seen.has(next))
|
|
34
|
+
continue;
|
|
35
|
+
const dependency = await ctx.resolve(next, id);
|
|
36
|
+
if (dependency !== null && !dependency.external)
|
|
37
|
+
queue.push(dependency);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return reachable;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=component-entries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-entries.js","sourceRoot":"","sources":["../../src/compiler/component-entries.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAyB,EACzB,MAAyB;IAEzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7B,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM;QAClC,MAAM,EAAE,EAAE,EAAE,GAAG,QAAQ,CAAC;QACxB,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,4BAA4B;YAAE,SAAS;QAClE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,oFAAoF;QACpF,yFAAyF;QACzF,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,QAAQ,CAAC,iBAAiB,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACtF,SAAS;QACX,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACpC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC7B,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/C,IAAI,UAAU,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["// Preserve components statically retained by the app entry instead of forcing another\n// dynamic-import entry for them (ADR 0016, gyral-1zd.31).\nimport type { Rollup } from 'vite';\n\n/**\n * Modules statically retained by the app's inputs (transitively). A component among them is\n * defined at startup by the app's own entry; giving it to the loader as well would make the\n * bundler split it out of the entry into a chunk of its own.\n */\nexport async function staticallyReachable(\n ctx: Rollup.PluginContext,\n inputs: readonly string[],\n): Promise<Set<string>> {\n const seen = new Set<string>();\n const reachable = new Set<string>();\n const entries = new Set<string>();\n const queue: Rollup.ResolvedId[] = [];\n for (const input of inputs) {\n const resolved = await ctx.resolve(input, undefined, { isEntry: true });\n if (resolved !== null && !resolved.external) {\n entries.add(resolved.id);\n queue.push(resolved);\n }\n }\n while (queue.length > 0) {\n const resolved = queue.pop();\n if (resolved === undefined) break;\n const { id } = resolved;\n if (seen.has(id) || id === '\\0virtual:gyral/components') continue;\n seen.add(id);\n const info = await ctx.load({ ...resolved, resolveDependencies: true });\n // A side-effect-only import can be dropped by tree shaking. Keep such components in\n // the loader rather than assuming the entry registered them (including through barrels).\n if ((info.moduleSideEffects ?? resolved.moduleSideEffects) === false && !entries.has(id))\n continue;\n reachable.add(id);\n for (const next of info.importedIds) {\n if (seen.has(next)) continue;\n const dependency = await ctx.resolve(next, id);\n if (dependency !== null && !dependency.external) queue.push(dependency);\n }\n }\n return reachable;\n}\n"]}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// Automatic component loading (`gyralVitePreset({ components })`, ADR 0016 addendum "Automatic
|
|
2
|
+
// component loading"): finds the app's components, adds a loader to the client build that
|
|
3
|
+
// imports a tag's module once the tag is in the page, and writes the manifest
|
|
4
|
+
// `@gyral/ssr/static`'s `componentsFromManifest` reads. ../vite.ts loads it on the plugin's
|
|
5
|
+
// first hook, as it loads the compiler.
|
|
6
|
+
import { relative, resolve, sep } from 'node:path';
|
|
7
|
+
import { staticallyReachable } from './component-entries.js';
|
|
8
|
+
import { loaderSource } from './loader-source.js';
|
|
9
|
+
import { discoverComponents } from './tag-map.js';
|
|
10
|
+
/** The loader module's id, and Vite's id for it (a virtual module). */
|
|
11
|
+
const COMPONENTS_ID = 'virtual:gyral/components';
|
|
12
|
+
const COMPONENTS_RESOLVED = `\0${COMPONENTS_ID}`;
|
|
13
|
+
/** The file the build writes next to `.vite/manifest.json` (read by `@gyral/ssr/static`). */
|
|
14
|
+
const COMPONENTS_MANIFEST = '.vite/gyral-components.json';
|
|
15
|
+
const SOURCE_FILE = /\.[cm]?[jt]sx?$/;
|
|
16
|
+
/**
|
|
17
|
+
* Tag → root-relative URL (`/src/…`) of the module defining it: ./tag-map.ts's scan, then the
|
|
18
|
+
* `modules` the app lists for components the scan can't see (defined through a wrapper).
|
|
19
|
+
*/
|
|
20
|
+
function scanComponents(root, include, listed = {}) {
|
|
21
|
+
const tags = new Map();
|
|
22
|
+
for (const [tag, path] of Object.entries(listed)) {
|
|
23
|
+
tags.set(tag, `/${relative(root, resolve(root, path)).split(sep).join('/')}`);
|
|
24
|
+
}
|
|
25
|
+
for (const { tag, file } of discoverComponents(root, include)) {
|
|
26
|
+
const url = `/${relative(root, file).split(sep).join('/')}`;
|
|
27
|
+
const known = tags.get(tag);
|
|
28
|
+
if (known === undefined)
|
|
29
|
+
tags.set(tag, url);
|
|
30
|
+
else if (known !== url && listed[tag] === undefined) {
|
|
31
|
+
console.warn(`gyral: <${tag}> is defined in ${known} and ${url}; loading ${known}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return tags;
|
|
35
|
+
}
|
|
36
|
+
/** The app's own inputs (everything but the loader), as module specifiers. */
|
|
37
|
+
function inputsOf(input) {
|
|
38
|
+
if (input === undefined)
|
|
39
|
+
return [];
|
|
40
|
+
if (typeof input === 'string')
|
|
41
|
+
return [input];
|
|
42
|
+
if (Array.isArray(input))
|
|
43
|
+
return [...input];
|
|
44
|
+
return Object.values(input);
|
|
45
|
+
}
|
|
46
|
+
/** The client build's input with the loader added. */
|
|
47
|
+
function withLoader(input) {
|
|
48
|
+
if (input === undefined)
|
|
49
|
+
return { components: COMPONENTS_ID };
|
|
50
|
+
if (typeof input === 'string') {
|
|
51
|
+
const name = input.replace(/^.*\//, '').replace(/\.[^.]*$/, '');
|
|
52
|
+
return withLoader({ [name]: input });
|
|
53
|
+
}
|
|
54
|
+
if (Array.isArray(input))
|
|
55
|
+
return [...input, COMPONENTS_ID];
|
|
56
|
+
const entries = input;
|
|
57
|
+
let name = 'components';
|
|
58
|
+
while (name in entries)
|
|
59
|
+
name += '-loader';
|
|
60
|
+
return { ...entries, [name]: COMPONENTS_ID };
|
|
61
|
+
}
|
|
62
|
+
/** Automatic component loading (`gyralVitePreset({ components })`). */
|
|
63
|
+
export function createComponents(options) {
|
|
64
|
+
const include = options.include ?? ['src'];
|
|
65
|
+
let root = process.cwd();
|
|
66
|
+
let tags = new Map();
|
|
67
|
+
/** The app's own build inputs, recorded before the loader is added. */
|
|
68
|
+
let appInputs = [];
|
|
69
|
+
/** Tags the app's entry defines itself (statically imported): not loaded by the loader. */
|
|
70
|
+
let entryTags = [];
|
|
71
|
+
let loaderFile = '';
|
|
72
|
+
const scan = () => (tags = scanComponents(root, include, options.modules));
|
|
73
|
+
const api = { tags: scan };
|
|
74
|
+
return {
|
|
75
|
+
name: 'gyral:components',
|
|
76
|
+
api,
|
|
77
|
+
config(config, env) {
|
|
78
|
+
root = resolve(config.root ?? process.cwd());
|
|
79
|
+
if (env.command !== 'build' || env.isSsrBuild === true)
|
|
80
|
+
return;
|
|
81
|
+
const build = (config.build ??= {});
|
|
82
|
+
const key = build.rolldownOptions !== undefined ? 'rolldownOptions' : 'rollupOptions';
|
|
83
|
+
const bundler = (build[key] ??= {});
|
|
84
|
+
const input = bundler.input ?? config.input;
|
|
85
|
+
appInputs = inputsOf(input);
|
|
86
|
+
bundler.input = withLoader(input);
|
|
87
|
+
build.manifest ??= true;
|
|
88
|
+
},
|
|
89
|
+
configResolved(config) {
|
|
90
|
+
root = config.root;
|
|
91
|
+
if (config.command !== 'build' || config.build.ssr !== false)
|
|
92
|
+
return;
|
|
93
|
+
const preload = config.build.modulePreload;
|
|
94
|
+
if (preload === false)
|
|
95
|
+
return;
|
|
96
|
+
const previous = preload.resolveDependencies;
|
|
97
|
+
preload.resolveDependencies = (file, deps, context) => context.hostType === 'js' && context.hostId === loaderFile
|
|
98
|
+
? []
|
|
99
|
+
: (previous?.(file, deps, context) ?? deps);
|
|
100
|
+
},
|
|
101
|
+
buildStart() {
|
|
102
|
+
scan();
|
|
103
|
+
},
|
|
104
|
+
resolveId(source) {
|
|
105
|
+
return source === COMPONENTS_ID ? COMPONENTS_RESOLVED : null;
|
|
106
|
+
},
|
|
107
|
+
async load(id) {
|
|
108
|
+
if (id !== COMPONENTS_RESOLVED)
|
|
109
|
+
return null;
|
|
110
|
+
if (this.environment.config.command === 'serve') {
|
|
111
|
+
scan();
|
|
112
|
+
return loaderSource(tags);
|
|
113
|
+
}
|
|
114
|
+
// A production build: components the app's entry imports are already defined at startup,
|
|
115
|
+
// and every other one becomes a dynamic import. The dependency filter removes repeated
|
|
116
|
+
// JS preload lists (renderPage already preloads them); Vite still loads their CSS.
|
|
117
|
+
const inEntry = await staticallyReachable(this, appInputs);
|
|
118
|
+
entryTags = [];
|
|
119
|
+
const lazy = new Map();
|
|
120
|
+
for (const [tag, url] of tags) {
|
|
121
|
+
const file = resolve(root, url.slice(1));
|
|
122
|
+
if (inEntry.has(file)) {
|
|
123
|
+
entryTags.push(tag);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
lazy.set(tag, url);
|
|
127
|
+
}
|
|
128
|
+
return loaderSource(lazy, { known: entryTags });
|
|
129
|
+
},
|
|
130
|
+
configureServer(server) {
|
|
131
|
+
// A new or edited component module changes the loader's table.
|
|
132
|
+
const refresh = (file) => {
|
|
133
|
+
if (!SOURCE_FILE.test(file))
|
|
134
|
+
return;
|
|
135
|
+
const module = server.environments.client.moduleGraph.getModuleById(COMPONENTS_RESOLVED);
|
|
136
|
+
if (module !== undefined)
|
|
137
|
+
server.environments.client.moduleGraph.invalidateModule(module);
|
|
138
|
+
};
|
|
139
|
+
server.watcher.on('add', refresh);
|
|
140
|
+
server.watcher.on('unlink', refresh);
|
|
141
|
+
server.watcher.on('change', refresh);
|
|
142
|
+
},
|
|
143
|
+
generateBundle(_output, bundle) {
|
|
144
|
+
if (this.environment.config.consumer !== 'client')
|
|
145
|
+
return;
|
|
146
|
+
const loader = Object.values(bundle).find((chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === COMPONENTS_RESOLVED);
|
|
147
|
+
if (loader?.type !== 'chunk')
|
|
148
|
+
return;
|
|
149
|
+
loaderFile = loader.fileName;
|
|
150
|
+
const modules = Object.fromEntries([...tags].map(([tag, url]) => [tag, url.slice(1)]));
|
|
151
|
+
// Each tag's chunk by file. A module another chunk imports statically is bundled into
|
|
152
|
+
// that chunk (often the entry), so Vite's manifest has no key for it; the server finds
|
|
153
|
+
// the chunk by file instead (`componentAssets`).
|
|
154
|
+
const chunkOf = new Map();
|
|
155
|
+
for (const chunk of Object.values(bundle)) {
|
|
156
|
+
if (chunk.type !== 'chunk')
|
|
157
|
+
continue;
|
|
158
|
+
for (const id of chunk.moduleIds)
|
|
159
|
+
chunkOf.set(id, chunk.fileName);
|
|
160
|
+
}
|
|
161
|
+
const chunks = {};
|
|
162
|
+
for (const [tag, url] of tags) {
|
|
163
|
+
const file = chunkOf.get(resolve(root, url.slice(1)));
|
|
164
|
+
if (file !== undefined)
|
|
165
|
+
chunks[tag] = file;
|
|
166
|
+
}
|
|
167
|
+
const written = {
|
|
168
|
+
loader: loader.fileName,
|
|
169
|
+
loaderImports: loader.imports,
|
|
170
|
+
modules,
|
|
171
|
+
chunks,
|
|
172
|
+
entryTags,
|
|
173
|
+
};
|
|
174
|
+
this.emitFile({
|
|
175
|
+
type: 'asset',
|
|
176
|
+
fileName: COMPONENTS_MANIFEST,
|
|
177
|
+
source: `${JSON.stringify(written, null, 2)}\n`,
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/compiler/components.ts"],"names":[],"mappings":"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","sourcesContent":["// Automatic component loading (`gyralVitePreset({ components })`, ADR 0016 addendum \"Automatic\n// component loading\"): finds the app's components, adds a loader to the client build that\n// imports a tag's module once the tag is in the page, and writes the manifest\n// `@gyral/ssr/static`'s `componentsFromManifest` reads. ../vite.ts loads it on the plugin's\n// first hook, as it loads the compiler.\nimport { relative, resolve, sep } from 'node:path';\nimport type { Plugin } from 'vite';\nimport { staticallyReachable } from './component-entries.js';\nimport type { ComponentsOptions } from '../vite.js';\nimport { loaderSource } from './loader-source.js';\nimport { discoverComponents } from './tag-map.js';\n\n/** The loader module's id, and Vite's id for it (a virtual module). */\nconst COMPONENTS_ID = 'virtual:gyral/components';\nconst COMPONENTS_RESOLVED = `\\0${COMPONENTS_ID}`;\n/** The file the build writes next to `.vite/manifest.json` (read by `@gyral/ssr/static`). */\nconst COMPONENTS_MANIFEST = '.vite/gyral-components.json';\n\nconst SOURCE_FILE = /\\.[cm]?[jt]sx?$/;\n\n/**\n * Tag → root-relative URL (`/src/…`) of the module defining it: ./tag-map.ts's scan, then the\n * `modules` the app lists for components the scan can't see (defined through a wrapper).\n */\nfunction scanComponents(\n root: string,\n include: readonly string[],\n listed: Readonly<Record<string, string>> = {},\n): Map<string, string> {\n const tags = new Map<string, string>();\n for (const [tag, path] of Object.entries(listed)) {\n tags.set(tag, `/${relative(root, resolve(root, path)).split(sep).join('/')}`);\n }\n for (const { tag, file } of discoverComponents(root, include)) {\n const url = `/${relative(root, file).split(sep).join('/')}`;\n const known = tags.get(tag);\n if (known === undefined) tags.set(tag, url);\n else if (known !== url && listed[tag] === undefined) {\n console.warn(`gyral: <${tag}> is defined in ${known} and ${url}; loading ${known}`);\n }\n }\n return tags;\n}\n\ntype Input = string | readonly string[] | Readonly<Record<string, string>> | undefined;\n\n/** The app's own inputs (everything but the loader), as module specifiers. */\nfunction inputsOf(input: Input): string[] {\n if (input === undefined) return [];\n if (typeof input === 'string') return [input];\n if (Array.isArray(input)) return [...(input as readonly string[])];\n return Object.values(input as Readonly<Record<string, string>>);\n}\n\n/** The client build's input with the loader added. */\nfunction withLoader(input: Input): string[] | Record<string, string> {\n if (input === undefined) return { components: COMPONENTS_ID };\n if (typeof input === 'string') {\n const name = input.replace(/^.*\\//, '').replace(/\\.[^.]*$/, '');\n return withLoader({ [name]: input });\n }\n if (Array.isArray(input)) return [...(input as readonly string[]), COMPONENTS_ID];\n const entries = input as Readonly<Record<string, string>>;\n let name = 'components';\n while (name in entries) name += '-loader';\n return { ...entries, [name]: COMPONENTS_ID };\n}\n\n/** The API `gyralDevServer` reads from this plugin (the tags it found, fresh). */\ninterface ComponentsPluginApi {\n readonly tags: () => ReadonlyMap<string, string>;\n}\n\n/** Automatic component loading (`gyralVitePreset({ components })`). */\nexport function createComponents(options: ComponentsOptions): Plugin {\n const include = options.include ?? ['src'];\n let root = process.cwd();\n let tags = new Map<string, string>();\n /** The app's own build inputs, recorded before the loader is added. */\n let appInputs: string[] = [];\n /** Tags the app's entry defines itself (statically imported): not loaded by the loader. */\n let entryTags: string[] = [];\n let loaderFile = '';\n const scan = (): Map<string, string> => (tags = scanComponents(root, include, options.modules));\n const api: ComponentsPluginApi = { tags: scan };\n return {\n name: 'gyral:components',\n api,\n config(config, env) {\n root = resolve(config.root ?? process.cwd());\n if (env.command !== 'build' || env.isSsrBuild === true) return;\n type Build = {\n manifest?: boolean | string;\n rollupOptions?: { input?: Input };\n rolldownOptions?: { input?: Input };\n };\n const build = ((config as { build?: Build }).build ??= {});\n const key = build.rolldownOptions !== undefined ? 'rolldownOptions' : 'rollupOptions';\n const bundler = (build[key] ??= {});\n const input = bundler.input ?? config.input;\n appInputs = inputsOf(input);\n bundler.input = withLoader(input);\n build.manifest ??= true;\n },\n configResolved(config) {\n root = config.root;\n if (config.command !== 'build' || config.build.ssr !== false) return;\n const preload = config.build.modulePreload;\n if (preload === false) return;\n const previous = preload.resolveDependencies;\n preload.resolveDependencies = (file, deps, context) =>\n context.hostType === 'js' && context.hostId === loaderFile\n ? []\n : (previous?.(file, deps, context) ?? deps);\n },\n buildStart() {\n scan();\n },\n resolveId(source) {\n return source === COMPONENTS_ID ? COMPONENTS_RESOLVED : null;\n },\n async load(id) {\n if (id !== COMPONENTS_RESOLVED) return null;\n if (this.environment.config.command === 'serve') {\n scan();\n return loaderSource(tags);\n }\n // A production build: components the app's entry imports are already defined at startup,\n // and every other one becomes a dynamic import. The dependency filter removes repeated\n // JS preload lists (renderPage already preloads them); Vite still loads their CSS.\n const inEntry = await staticallyReachable(this, appInputs);\n entryTags = [];\n const lazy = new Map<string, string>();\n for (const [tag, url] of tags) {\n const file = resolve(root, url.slice(1));\n if (inEntry.has(file)) {\n entryTags.push(tag);\n continue;\n }\n lazy.set(tag, url);\n }\n return loaderSource(lazy, { known: entryTags });\n },\n configureServer(server) {\n // A new or edited component module changes the loader's table.\n const refresh = (file: string): void => {\n if (!SOURCE_FILE.test(file)) return;\n const module = server.environments.client.moduleGraph.getModuleById(COMPONENTS_RESOLVED);\n if (module !== undefined) server.environments.client.moduleGraph.invalidateModule(module);\n };\n server.watcher.on('add', refresh);\n server.watcher.on('unlink', refresh);\n server.watcher.on('change', refresh);\n },\n generateBundle(_output, bundle) {\n if (this.environment.config.consumer !== 'client') return;\n const loader = Object.values(bundle).find(\n (chunk) => chunk.type === 'chunk' && chunk.facadeModuleId === COMPONENTS_RESOLVED,\n );\n if (loader?.type !== 'chunk') return;\n loaderFile = loader.fileName;\n const modules = Object.fromEntries([...tags].map(([tag, url]) => [tag, url.slice(1)]));\n // Each tag's chunk by file. A module another chunk imports statically is bundled into\n // that chunk (often the entry), so Vite's manifest has no key for it; the server finds\n // the chunk by file instead (`componentAssets`).\n const chunkOf = new Map<string, string>();\n for (const chunk of Object.values(bundle)) {\n if (chunk.type !== 'chunk') continue;\n for (const id of chunk.moduleIds) chunkOf.set(id, chunk.fileName);\n }\n const chunks: Record<string, string> = {};\n for (const [tag, url] of tags) {\n const file = chunkOf.get(resolve(root, url.slice(1)));\n if (file !== undefined) chunks[tag] = file;\n }\n const written = {\n loader: loader.fileName,\n loaderImports: loader.imports,\n modules,\n chunks,\n entryTags,\n };\n this.emitFile({\n type: 'asset',\n fileName: COMPONENTS_MANIFEST,\n source: `${JSON.stringify(written, null, 2)}\\n`,\n });\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Node } from './ast.js';
|
|
2
|
+
/** Optional machinery the build adds when a module may use it. */
|
|
3
|
+
export type Feature = 'invokers' | 'transitions' | 'frame' | 'states' | 'forms' | 'subscriptions' | 'dialogs' | 'disposal' | 'errorView' | 'errored';
|
|
4
|
+
/** The spec field each spec-field feature is reached through (04, 05). */
|
|
5
|
+
export declare const FIELDS: {
|
|
6
|
+
readonly transitions: "viewTransition";
|
|
7
|
+
readonly frame: "renderOnFrame";
|
|
8
|
+
readonly states: "states";
|
|
9
|
+
readonly forms: "formAssociated";
|
|
10
|
+
readonly subscriptions: "subscriptions";
|
|
11
|
+
readonly disposal: "dispose";
|
|
12
|
+
readonly errorView: "error";
|
|
13
|
+
readonly errored: "Errored";
|
|
14
|
+
};
|
|
15
|
+
export interface ModuleFacts {
|
|
16
|
+
/** Identifier names in runtime code, import declarations left out. */
|
|
17
|
+
readonly names: ReadonlySet<string>;
|
|
18
|
+
/** String literal values, and template literal texts with `${}` for each expression. */
|
|
19
|
+
readonly texts: readonly string[];
|
|
20
|
+
/** Specifiers through which the module may reach a `raw` export (see the header). */
|
|
21
|
+
readonly rawSources: readonly string[];
|
|
22
|
+
/** Whether the module may give a component an error view (see `specError`). */
|
|
23
|
+
readonly errorView: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The facts the scan needs about a module (`program`, from `this.parse`). */
|
|
26
|
+
export declare function factsOf(program: Node): ModuleFacts;
|
|
27
|
+
/**
|
|
28
|
+
* Whether the module may use `feature` by what it writes itself. For `invokers` that is the
|
|
29
|
+
* markup and strings; `raw` needs resolving `rawSources` (features.ts).
|
|
30
|
+
*/
|
|
31
|
+
export declare function writes(facts: ModuleFacts, feature: Feature): boolean;
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
// What one module may use, for the build-time feature scan (features.ts, view/05-element.md
|
|
2
|
+
// "Features register themselves"), read from its AST (Rolldown's `this.parse`, the author's
|
|
3
|
+
// source: both plugins that scan run before other transforms). Comments are not in the AST,
|
|
4
|
+
// and type-only code is skipped (ast.ts `children`), so neither counts. What does:
|
|
5
|
+
// - spec fields (`viewTransition`, `renderOnFrame`, `states`, `subscriptions`) and the hook
|
|
6
|
+
// spec key `dispose`: the name as an identifier
|
|
7
|
+
// anywhere in runtime code (a property key, `spec.states = …`, `{ states }`, a binding a
|
|
8
|
+
// namespace import may spread, `export { f as states }`), or a string that is exactly the
|
|
9
|
+
// name (`Object.defineProperty(spec, 'states', …)`). A word inside a longer string doesn't;
|
|
10
|
+
// - command intents: a string or template whose markup has a `data-intent-command` attribute,
|
|
11
|
+
// `data-intent-on="command"` or a bound `data-intent-on`, or a string that is exactly "command" (`events: ['command']`, a
|
|
12
|
+
// `setAttribute`);
|
|
13
|
+
// - dialog and popover bindings: a template whose markup binds `?modal=` or `?popover-open=`;
|
|
14
|
+
// - `raw` (its markup is read at run time, so it may hold `data-intent-on="command"`): the
|
|
15
|
+
// module lists the specifiers through which it may reach a `raw` export, and features.ts
|
|
16
|
+
// counts it when one of them is a module of `@gyral/core`. Through: a named import of `raw` (any
|
|
17
|
+
// alias) that the module references; a namespace import read other than as `ns.<name>`
|
|
18
|
+
// (`ns.raw`, `ns[key]`, the namespace passed on); a re-export of `raw`, `export *`; a
|
|
19
|
+
// dynamic `import()`. A module that re-exports core's `raw` counts itself, so `raw`
|
|
20
|
+
// imported through a re-exporting module (the app's, a design system's) is still seen there.
|
|
21
|
+
import { children, nodeAt, nodesAt } from './ast.js';
|
|
22
|
+
/** The spec field each spec-field feature is reached through (04, 05). */
|
|
23
|
+
export const FIELDS = {
|
|
24
|
+
transitions: 'viewTransition',
|
|
25
|
+
frame: 'renderOnFrame',
|
|
26
|
+
states: 'states',
|
|
27
|
+
forms: 'formAssociated',
|
|
28
|
+
subscriptions: 'subscriptions',
|
|
29
|
+
disposal: 'dispose',
|
|
30
|
+
errorView: 'error',
|
|
31
|
+
errored: 'Errored',
|
|
32
|
+
};
|
|
33
|
+
/** Markup that binds the dialog or popover state (`?modal=`, `?popover-open=`, view/02). */
|
|
34
|
+
const TOGGLE_BINDING = /\?(?:modal|popover-open)\s*=/i;
|
|
35
|
+
/**
|
|
36
|
+
* Markup that makes a root listen for `command` (05 "Intent events"): a `data-intent-command`
|
|
37
|
+
* attribute (static or bound; a string that is exactly its name, as `setAttribute` takes it), a
|
|
38
|
+
* static `data-intent-on="command"` (quoted or not, alone or in a quoted list), or a bound
|
|
39
|
+
* `data-intent-on` (all intent events), which a template's text shows as `${}` where its
|
|
40
|
+
* expression is, and a string as an unfinished value at its end. The attribute's name is matched in any case, as the runtime reads it.
|
|
41
|
+
*/
|
|
42
|
+
const INTENT_ON_COMMAND = /data-intent-command(?:\s*=|$)|data-intent-on\s*=\s*(?:["'][^"'>]*?(?:(?<![\w-])command(?![\w-])|\$\{\}|$)|command(?![\w-])|[^"'\s>]*(?:\$\{\}|$))/i;
|
|
43
|
+
const stringOf = (node) => {
|
|
44
|
+
if (node?.type === 'Literal')
|
|
45
|
+
return typeof node['value'] === 'string' ? node['value'] : undefined;
|
|
46
|
+
if (node?.type !== 'TemplateLiteral' || nodesAt(node, 'expressions').length > 0)
|
|
47
|
+
return undefined;
|
|
48
|
+
return templateText(node);
|
|
49
|
+
};
|
|
50
|
+
/** A template literal's text (cooked where valid), `${}` standing for each expression. */
|
|
51
|
+
function templateText(node) {
|
|
52
|
+
return nodesAt(node, 'quasis')
|
|
53
|
+
.map((q) => {
|
|
54
|
+
const value = q['value'];
|
|
55
|
+
return value?.cooked ?? value?.raw ?? '';
|
|
56
|
+
})
|
|
57
|
+
.join('${}');
|
|
58
|
+
}
|
|
59
|
+
/** An identifier's name, or a string literal's value (`import { 'raw' as r }`). */
|
|
60
|
+
const nameOf = (node) => node?.type === 'Identifier' ? node['name'] : stringOf(node);
|
|
61
|
+
const isValue = (node) => node['importKind'] !== 'type' && node['exportKind'] !== 'type';
|
|
62
|
+
const bump = (counts, name) => {
|
|
63
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
64
|
+
};
|
|
65
|
+
const FUNCTION = new Set(['ArrowFunctionExpression', 'FunctionExpression']);
|
|
66
|
+
/** A callee named `define` (`define`, `ns.define`), or the inner call of `define<…>()(…)`. */
|
|
67
|
+
function isDefine(callee) {
|
|
68
|
+
if (callee?.type === 'CallExpression')
|
|
69
|
+
return isDefine(nodeAt(callee, 'callee'));
|
|
70
|
+
if (callee?.type === 'Identifier')
|
|
71
|
+
return callee['name'] === 'define';
|
|
72
|
+
if (callee?.type === 'MemberExpression' && callee['computed'] !== true)
|
|
73
|
+
return nameOf(nodeAt(callee, 'property')) === 'define';
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The `error` spec field (ADR 0024) by its position, not its name, because `error` is also a
|
|
78
|
+
* common state field, `catch (error)` binding and message name (gyral-1zd.29). It counts:
|
|
79
|
+
* - an `error` key (any value) in a spec object passed to `define()`, inline or through a
|
|
80
|
+
* `const` in the same module, spreads of such consts included;
|
|
81
|
+
* - anywhere else, an `error` key whose value is a function (`error: (failure, s) => …`,
|
|
82
|
+
* `error(failure, s) { … }`) or a shorthand `{ error }`, and an assignment of a function to
|
|
83
|
+
* a member `x.error` (a spec built elsewhere and passed in).
|
|
84
|
+
* What it misses: a spec object built in another module whose `error` value isn't written as a
|
|
85
|
+
* function there (`export const spec = { error: someView }`); view/05 says to write the error
|
|
86
|
+
* view as a function in the spec.
|
|
87
|
+
*/
|
|
88
|
+
function specError(program) {
|
|
89
|
+
const objects = new Map();
|
|
90
|
+
let found = false;
|
|
91
|
+
const keyOf = (prop) => prop['computed'] === true ? undefined : nameOf(nodeAt(prop, 'key'));
|
|
92
|
+
const specHasError = (node, depth = 0) => {
|
|
93
|
+
if (node?.type === 'Identifier' && depth < 3) {
|
|
94
|
+
return specHasError(objects.get(node['name']), depth + 1);
|
|
95
|
+
}
|
|
96
|
+
if (node?.type !== 'ObjectExpression')
|
|
97
|
+
return false;
|
|
98
|
+
return nodesAt(node, 'properties').some((p) => p.type === 'SpreadElement'
|
|
99
|
+
? specHasError(nodeAt(p, 'argument'), depth + 1)
|
|
100
|
+
: keyOf(p) === 'error');
|
|
101
|
+
};
|
|
102
|
+
const collect = (node) => {
|
|
103
|
+
if (node.type === 'VariableDeclarator') {
|
|
104
|
+
const id = nodeAt(node, 'id');
|
|
105
|
+
const init = nodeAt(node, 'init');
|
|
106
|
+
if (id?.type === 'Identifier' && init?.type === 'ObjectExpression')
|
|
107
|
+
objects.set(id['name'], init);
|
|
108
|
+
}
|
|
109
|
+
for (const child of children(node))
|
|
110
|
+
collect(child);
|
|
111
|
+
};
|
|
112
|
+
const visit = (node) => {
|
|
113
|
+
if (found)
|
|
114
|
+
return;
|
|
115
|
+
switch (node.type) {
|
|
116
|
+
case 'CallExpression':
|
|
117
|
+
if (isDefine(nodeAt(node, 'callee'))) {
|
|
118
|
+
const args = nodesAt(node, 'arguments');
|
|
119
|
+
if (args.some((a) => specHasError(a)))
|
|
120
|
+
found = true;
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
case 'Property':
|
|
124
|
+
case 'MethodDefinition':
|
|
125
|
+
case 'PropertyDefinition':
|
|
126
|
+
if (keyOf(node) === 'error') {
|
|
127
|
+
const value = nodeAt(node, 'value');
|
|
128
|
+
if (node['shorthand'] === true ||
|
|
129
|
+
node['method'] === true ||
|
|
130
|
+
node.type === 'MethodDefinition' ||
|
|
131
|
+
(value !== undefined && FUNCTION.has(value.type))) {
|
|
132
|
+
found = true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
case 'AssignmentExpression': {
|
|
137
|
+
const left = nodeAt(node, 'left');
|
|
138
|
+
const right = nodeAt(node, 'right');
|
|
139
|
+
if (left?.type === 'MemberExpression' &&
|
|
140
|
+
left['computed'] !== true &&
|
|
141
|
+
nameOf(nodeAt(left, 'property')) === 'error' &&
|
|
142
|
+
right !== undefined &&
|
|
143
|
+
FUNCTION.has(right.type)) {
|
|
144
|
+
found = true;
|
|
145
|
+
}
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (const child of children(node))
|
|
150
|
+
visit(child);
|
|
151
|
+
};
|
|
152
|
+
for (const statement of nodesAt(program, 'body'))
|
|
153
|
+
collect(statement);
|
|
154
|
+
for (const statement of nodesAt(program, 'body'))
|
|
155
|
+
visit(statement);
|
|
156
|
+
return found;
|
|
157
|
+
}
|
|
158
|
+
/** The facts the scan needs about a module (`program`, from `this.parse`). */
|
|
159
|
+
export function factsOf(program) {
|
|
160
|
+
/** Every identifier name, and how often each is referenced (property names left out). */
|
|
161
|
+
const names = new Set();
|
|
162
|
+
const refs = new Map();
|
|
163
|
+
const texts = [];
|
|
164
|
+
const reached = [];
|
|
165
|
+
/** Imports of `raw` (local name → specifier), and namespace imports. */
|
|
166
|
+
const rawImports = new Map();
|
|
167
|
+
const namespaces = new Map();
|
|
168
|
+
/** Per namespace, the reads `ns.<name other than raw>`: they can't reach `raw`. */
|
|
169
|
+
const safe = new Map();
|
|
170
|
+
for (const statement of nodesAt(program, 'body')) {
|
|
171
|
+
const specifier = stringOf(nodeAt(statement, 'source'));
|
|
172
|
+
if (specifier === undefined || !isValue(statement))
|
|
173
|
+
continue;
|
|
174
|
+
if (statement.type === 'ImportDeclaration') {
|
|
175
|
+
for (const s of nodesAt(statement, 'specifiers')) {
|
|
176
|
+
const local = nameOf(nodeAt(s, 'local'));
|
|
177
|
+
if (local === undefined || !isValue(s))
|
|
178
|
+
continue;
|
|
179
|
+
if (s.type === 'ImportNamespaceSpecifier')
|
|
180
|
+
namespaces.set(local, specifier);
|
|
181
|
+
else if (s.type === 'ImportSpecifier' && nameOf(nodeAt(s, 'imported')) === 'raw')
|
|
182
|
+
rawImports.set(local, specifier);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else if (statement.type === 'ExportAllDeclaration') {
|
|
186
|
+
reached.push(specifier);
|
|
187
|
+
}
|
|
188
|
+
else if (statement.type === 'ExportNamedDeclaration') {
|
|
189
|
+
const specifiers = nodesAt(statement, 'specifiers');
|
|
190
|
+
if (specifiers.some((s) => isValue(s) && nameOf(nodeAt(s, 'local')) === 'raw'))
|
|
191
|
+
reached.push(specifier);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** A non-computed property name (`{ key: … }`, `a.key`, a class member): not a reference. */
|
|
195
|
+
const key = (node) => {
|
|
196
|
+
if (node?.type === 'Identifier')
|
|
197
|
+
names.add(node['name']);
|
|
198
|
+
else if (node !== undefined)
|
|
199
|
+
visit(node);
|
|
200
|
+
};
|
|
201
|
+
const visit = (node) => {
|
|
202
|
+
switch (node.type) {
|
|
203
|
+
case 'ImportDeclaration':
|
|
204
|
+
return;
|
|
205
|
+
case 'Identifier':
|
|
206
|
+
case 'JSXIdentifier':
|
|
207
|
+
names.add(node['name']);
|
|
208
|
+
bump(refs, node['name']);
|
|
209
|
+
return;
|
|
210
|
+
case 'Literal':
|
|
211
|
+
if (typeof node['value'] === 'string')
|
|
212
|
+
texts.push(node['value']);
|
|
213
|
+
return;
|
|
214
|
+
case 'TemplateLiteral':
|
|
215
|
+
texts.push(templateText(node));
|
|
216
|
+
break;
|
|
217
|
+
case 'ImportExpression': {
|
|
218
|
+
const specifier = stringOf(nodeAt(node, 'source'));
|
|
219
|
+
if (specifier !== undefined)
|
|
220
|
+
reached.push(specifier);
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case 'MemberExpression': {
|
|
224
|
+
const object = nodeAt(node, 'object');
|
|
225
|
+
const property = nodeAt(node, 'property');
|
|
226
|
+
const computed = node['computed'] === true;
|
|
227
|
+
const ns = object?.type === 'Identifier' ? object['name'] : undefined;
|
|
228
|
+
if (ns !== undefined && namespaces.has(ns)) {
|
|
229
|
+
const name = computed ? stringOf(property) : nameOf(property);
|
|
230
|
+
if (name !== undefined && name !== 'raw')
|
|
231
|
+
bump(safe, ns);
|
|
232
|
+
}
|
|
233
|
+
if (object !== undefined)
|
|
234
|
+
visit(object);
|
|
235
|
+
if (computed) {
|
|
236
|
+
if (property !== undefined)
|
|
237
|
+
visit(property);
|
|
238
|
+
}
|
|
239
|
+
else
|
|
240
|
+
key(property);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
case 'Property':
|
|
244
|
+
case 'MethodDefinition':
|
|
245
|
+
case 'PropertyDefinition':
|
|
246
|
+
case 'AccessorProperty':
|
|
247
|
+
if (node['computed'] === true || node['shorthand'] === true)
|
|
248
|
+
break;
|
|
249
|
+
key(nodeAt(node, 'key'));
|
|
250
|
+
for (const child of children(node))
|
|
251
|
+
if (child !== nodeAt(node, 'key'))
|
|
252
|
+
visit(child);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
for (const child of children(node))
|
|
256
|
+
visit(child);
|
|
257
|
+
};
|
|
258
|
+
for (const statement of nodesAt(program, 'body'))
|
|
259
|
+
visit(statement);
|
|
260
|
+
for (const [local, specifier] of rawImports) {
|
|
261
|
+
if ((refs.get(local) ?? 0) > 0)
|
|
262
|
+
reached.push(specifier);
|
|
263
|
+
}
|
|
264
|
+
for (const [local, specifier] of namespaces) {
|
|
265
|
+
if ((refs.get(local) ?? 0) > (safe.get(local) ?? 0))
|
|
266
|
+
reached.push(specifier);
|
|
267
|
+
}
|
|
268
|
+
return { names, texts, rawSources: [...new Set(reached)], errorView: specError(program) };
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Whether the module may use `feature` by what it writes itself. For `invokers` that is the
|
|
272
|
+
* markup and strings; `raw` needs resolving `rawSources` (features.ts).
|
|
273
|
+
*/
|
|
274
|
+
export function writes(facts, feature) {
|
|
275
|
+
if (feature === 'invokers') {
|
|
276
|
+
return facts.texts.some((text) => text === 'command' || INTENT_ON_COMMAND.test(text));
|
|
277
|
+
}
|
|
278
|
+
if (feature === 'dialogs')
|
|
279
|
+
return facts.texts.some((text) => TOGGLE_BINDING.test(text));
|
|
280
|
+
if (feature === 'errorView')
|
|
281
|
+
return facts.errorView;
|
|
282
|
+
const name = FIELDS[feature];
|
|
283
|
+
return facts.names.has(name) || facts.texts.includes(name);
|
|
284
|
+
}
|
|
285
|
+
//# sourceMappingURL=facts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facts.js","sourceRoot":"","sources":["../../src/compiler/facts.ts"],"names":[],"mappings":"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","sourcesContent":["// What one module may use, for the build-time feature scan (features.ts, view/05-element.md\n// \"Features register themselves\"), read from its AST (Rolldown's `this.parse`, the author's\n// source: both plugins that scan run before other transforms). Comments are not in the AST,\n// and type-only code is skipped (ast.ts `children`), so neither counts. What does:\n// - spec fields (`viewTransition`, `renderOnFrame`, `states`, `subscriptions`) and the hook\n// spec key `dispose`: the name as an identifier\n// anywhere in runtime code (a property key, `spec.states = …`, `{ states }`, a binding a\n// namespace import may spread, `export { f as states }`), or a string that is exactly the\n// name (`Object.defineProperty(spec, 'states', …)`). A word inside a longer string doesn't;\n// - command intents: a string or template whose markup has a `data-intent-command` attribute,\n// `data-intent-on=\"command\"` or a bound `data-intent-on`, or a string that is exactly \"command\" (`events: ['command']`, a\n// `setAttribute`);\n// - dialog and popover bindings: a template whose markup binds `?modal=` or `?popover-open=`;\n// - `raw` (its markup is read at run time, so it may hold `data-intent-on=\"command\"`): the\n// module lists the specifiers through which it may reach a `raw` export, and features.ts\n// counts it when one of them is a module of `@gyral/core`. Through: a named import of `raw` (any\n// alias) that the module references; a namespace import read other than as `ns.<name>`\n// (`ns.raw`, `ns[key]`, the namespace passed on); a re-export of `raw`, `export *`; a\n// dynamic `import()`. A module that re-exports core's `raw` counts itself, so `raw`\n// imported through a re-exporting module (the app's, a design system's) is still seen there.\nimport { children, nodeAt, nodesAt, type Node } from './ast.js';\n\n/** Optional machinery the build adds when a module may use it. */\nexport type Feature =\n | 'invokers'\n | 'transitions'\n | 'frame'\n | 'states'\n | 'forms'\n | 'subscriptions'\n | 'dialogs'\n | 'disposal'\n | 'errorView'\n | 'errored';\n\n/** The spec field each spec-field feature is reached through (04, 05). */\nexport const FIELDS = {\n transitions: 'viewTransition',\n frame: 'renderOnFrame',\n states: 'states',\n forms: 'formAssociated',\n subscriptions: 'subscriptions',\n disposal: 'dispose',\n errorView: 'error',\n errored: 'Errored',\n} as const satisfies Readonly<Record<Exclude<Feature, 'invokers' | 'dialogs'>, string>>;\n\n/** Markup that binds the dialog or popover state (`?modal=`, `?popover-open=`, view/02). */\nconst TOGGLE_BINDING = /\\?(?:modal|popover-open)\\s*=/i;\n\n/**\n * Markup that makes a root listen for `command` (05 \"Intent events\"): a `data-intent-command`\n * attribute (static or bound; a string that is exactly its name, as `setAttribute` takes it), a\n * static `data-intent-on=\"command\"` (quoted or not, alone or in a quoted list), or a bound\n * `data-intent-on` (all intent events), which a template's text shows as `${}` where its\n * expression is, and a string as an unfinished value at its end. The attribute's name is matched in any case, as the runtime reads it.\n */\nconst INTENT_ON_COMMAND =\n /data-intent-command(?:\\s*=|$)|data-intent-on\\s*=\\s*(?:[\"'][^\"'>]*?(?:(?<![\\w-])command(?![\\w-])|\\$\\{\\}|$)|command(?![\\w-])|[^\"'\\s>]*(?:\\$\\{\\}|$))/i;\n\nexport interface ModuleFacts {\n /** Identifier names in runtime code, import declarations left out. */\n readonly names: ReadonlySet<string>;\n /** String literal values, and template literal texts with `${}` for each expression. */\n readonly texts: readonly string[];\n /** Specifiers through which the module may reach a `raw` export (see the header). */\n readonly rawSources: readonly string[];\n /** Whether the module may give a component an error view (see `specError`). */\n readonly errorView: boolean;\n}\n\nconst stringOf = (node: Node | undefined): string | undefined => {\n if (node?.type === 'Literal')\n return typeof node['value'] === 'string' ? node['value'] : undefined;\n if (node?.type !== 'TemplateLiteral' || nodesAt(node, 'expressions').length > 0) return undefined;\n return templateText(node);\n};\n\n/** A template literal's text (cooked where valid), `${}` standing for each expression. */\nfunction templateText(node: Node): string {\n return nodesAt(node, 'quasis')\n .map((q) => {\n const value = q['value'] as { cooked?: string | null; raw?: string } | undefined;\n return value?.cooked ?? value?.raw ?? '';\n })\n .join('${}');\n}\n\n/** An identifier's name, or a string literal's value (`import { 'raw' as r }`). */\nconst nameOf = (node: Node | undefined): string | undefined =>\n node?.type === 'Identifier' ? (node['name'] as string) : stringOf(node);\n\nconst isValue = (node: Node): boolean =>\n node['importKind'] !== 'type' && node['exportKind'] !== 'type';\n\nconst bump = (counts: Map<string, number>, name: string): void => {\n counts.set(name, (counts.get(name) ?? 0) + 1);\n};\n\nconst FUNCTION = new Set(['ArrowFunctionExpression', 'FunctionExpression']);\n\n/** A callee named `define` (`define`, `ns.define`), or the inner call of `define<…>()(…)`. */\nfunction isDefine(callee: Node | undefined): boolean {\n if (callee?.type === 'CallExpression') return isDefine(nodeAt(callee, 'callee'));\n if (callee?.type === 'Identifier') return callee['name'] === 'define';\n if (callee?.type === 'MemberExpression' && callee['computed'] !== true)\n return nameOf(nodeAt(callee, 'property')) === 'define';\n return false;\n}\n\n/**\n * The `error` spec field (ADR 0024) by its position, not its name, because `error` is also a\n * common state field, `catch (error)` binding and message name (gyral-1zd.29). It counts:\n * - an `error` key (any value) in a spec object passed to `define()`, inline or through a\n * `const` in the same module, spreads of such consts included;\n * - anywhere else, an `error` key whose value is a function (`error: (failure, s) => …`,\n * `error(failure, s) { … }`) or a shorthand `{ error }`, and an assignment of a function to\n * a member `x.error` (a spec built elsewhere and passed in).\n * What it misses: a spec object built in another module whose `error` value isn't written as a\n * function there (`export const spec = { error: someView }`); view/05 says to write the error\n * view as a function in the spec.\n */\nfunction specError(program: Node): boolean {\n const objects = new Map<string, Node>();\n let found = false;\n const keyOf = (prop: Node): string | undefined =>\n prop['computed'] === true ? undefined : nameOf(nodeAt(prop, 'key'));\n const specHasError = (node: Node | undefined, depth = 0): boolean => {\n if (node?.type === 'Identifier' && depth < 3) {\n return specHasError(objects.get(node['name'] as string), depth + 1);\n }\n if (node?.type !== 'ObjectExpression') return false;\n return nodesAt(node, 'properties').some((p) =>\n p.type === 'SpreadElement'\n ? specHasError(nodeAt(p, 'argument'), depth + 1)\n : keyOf(p) === 'error',\n );\n };\n const collect = (node: Node): void => {\n if (node.type === 'VariableDeclarator') {\n const id = nodeAt(node, 'id');\n const init = nodeAt(node, 'init');\n if (id?.type === 'Identifier' && init?.type === 'ObjectExpression')\n objects.set(id['name'] as string, init);\n }\n for (const child of children(node)) collect(child);\n };\n const visit = (node: Node): void => {\n if (found) return;\n switch (node.type) {\n case 'CallExpression':\n if (isDefine(nodeAt(node, 'callee'))) {\n const args = nodesAt(node, 'arguments');\n if (args.some((a) => specHasError(a))) found = true;\n }\n break;\n case 'Property':\n case 'MethodDefinition':\n case 'PropertyDefinition':\n if (keyOf(node) === 'error') {\n const value = nodeAt(node, 'value');\n if (\n node['shorthand'] === true ||\n node['method'] === true ||\n node.type === 'MethodDefinition' ||\n (value !== undefined && FUNCTION.has(value.type))\n ) {\n found = true;\n }\n }\n break;\n case 'AssignmentExpression': {\n const left = nodeAt(node, 'left');\n const right = nodeAt(node, 'right');\n if (\n left?.type === 'MemberExpression' &&\n left['computed'] !== true &&\n nameOf(nodeAt(left, 'property')) === 'error' &&\n right !== undefined &&\n FUNCTION.has(right.type)\n ) {\n found = true;\n }\n break;\n }\n }\n for (const child of children(node)) visit(child);\n };\n for (const statement of nodesAt(program, 'body')) collect(statement);\n for (const statement of nodesAt(program, 'body')) visit(statement);\n return found;\n}\n\n/** The facts the scan needs about a module (`program`, from `this.parse`). */\nexport function factsOf(program: Node): ModuleFacts {\n /** Every identifier name, and how often each is referenced (property names left out). */\n const names = new Set<string>();\n const refs = new Map<string, number>();\n const texts: string[] = [];\n const reached: string[] = [];\n /** Imports of `raw` (local name → specifier), and namespace imports. */\n const rawImports = new Map<string, string>();\n const namespaces = new Map<string, string>();\n /** Per namespace, the reads `ns.<name other than raw>`: they can't reach `raw`. */\n const safe = new Map<string, number>();\n\n for (const statement of nodesAt(program, 'body')) {\n const specifier = stringOf(nodeAt(statement, 'source'));\n if (specifier === undefined || !isValue(statement)) continue;\n if (statement.type === 'ImportDeclaration') {\n for (const s of nodesAt(statement, 'specifiers')) {\n const local = nameOf(nodeAt(s, 'local'));\n if (local === undefined || !isValue(s)) continue;\n if (s.type === 'ImportNamespaceSpecifier') namespaces.set(local, specifier);\n else if (s.type === 'ImportSpecifier' && nameOf(nodeAt(s, 'imported')) === 'raw')\n rawImports.set(local, specifier);\n }\n } else if (statement.type === 'ExportAllDeclaration') {\n reached.push(specifier);\n } else if (statement.type === 'ExportNamedDeclaration') {\n const specifiers = nodesAt(statement, 'specifiers');\n if (specifiers.some((s) => isValue(s) && nameOf(nodeAt(s, 'local')) === 'raw'))\n reached.push(specifier);\n }\n }\n\n /** A non-computed property name (`{ key: … }`, `a.key`, a class member): not a reference. */\n const key = (node: Node | undefined): void => {\n if (node?.type === 'Identifier') names.add(node['name'] as string);\n else if (node !== undefined) visit(node);\n };\n\n const visit = (node: Node): void => {\n switch (node.type) {\n case 'ImportDeclaration':\n return;\n case 'Identifier':\n case 'JSXIdentifier':\n names.add(node['name'] as string);\n bump(refs, node['name'] as string);\n return;\n case 'Literal':\n if (typeof node['value'] === 'string') texts.push(node['value']);\n return;\n case 'TemplateLiteral':\n texts.push(templateText(node));\n break;\n case 'ImportExpression': {\n const specifier = stringOf(nodeAt(node, 'source'));\n if (specifier !== undefined) reached.push(specifier);\n break;\n }\n case 'MemberExpression': {\n const object = nodeAt(node, 'object');\n const property = nodeAt(node, 'property');\n const computed = node['computed'] === true;\n const ns = object?.type === 'Identifier' ? (object['name'] as string) : undefined;\n if (ns !== undefined && namespaces.has(ns)) {\n const name = computed ? stringOf(property) : nameOf(property);\n if (name !== undefined && name !== 'raw') bump(safe, ns);\n }\n if (object !== undefined) visit(object);\n if (computed) {\n if (property !== undefined) visit(property);\n } else key(property);\n return;\n }\n case 'Property':\n case 'MethodDefinition':\n case 'PropertyDefinition':\n case 'AccessorProperty':\n if (node['computed'] === true || node['shorthand'] === true) break;\n key(nodeAt(node, 'key'));\n for (const child of children(node)) if (child !== nodeAt(node, 'key')) visit(child);\n return;\n }\n for (const child of children(node)) visit(child);\n };\n for (const statement of nodesAt(program, 'body')) visit(statement);\n\n for (const [local, specifier] of rawImports) {\n if ((refs.get(local) ?? 0) > 0) reached.push(specifier);\n }\n for (const [local, specifier] of namespaces) {\n if ((refs.get(local) ?? 0) > (safe.get(local) ?? 0)) reached.push(specifier);\n }\n return { names, texts, rawSources: [...new Set(reached)], errorView: specError(program) };\n}\n\n/**\n * Whether the module may use `feature` by what it writes itself. For `invokers` that is the\n * markup and strings; `raw` needs resolving `rawSources` (features.ts).\n */\nexport function writes(facts: ModuleFacts, feature: Feature): boolean {\n if (feature === 'invokers') {\n return facts.texts.some((text) => text === 'command' || INTENT_ON_COMMAND.test(text));\n }\n if (feature === 'dialogs') return facts.texts.some((text) => TOGGLE_BINDING.test(text));\n if (feature === 'errorView') return facts.errorView;\n const name = FIELDS[feature];\n return facts.names.has(name) || facts.texts.includes(name);\n}\n"]}
|