@gyral/core 0.3.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 +42 -0
- package/NOTICE +19 -0
- package/README.md +30 -5
- 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 +25 -3
- package/dist/children.js +18 -1
- 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 +25 -11
- package/dist/command.js.map +1 -1
- package/dist/compiler/ast.d.ts +2 -0
- package/dist/compiler/ast.js +5 -1
- package/dist/compiler/ast.js.map +1 -1
- package/dist/compiler/compile.d.ts +5 -2
- package/dist/compiler/compile.js +36 -17
- package/dist/compiler/compile.js.map +1 -1
- 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 +4 -0
- package/dist/compiler/hooks.js +144 -89
- package/dist/compiler/hooks.js.map +1 -1
- 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 +1 -1
- package/dist/compiler/parse5-check.js +8 -3
- package/dist/compiler/parse5-check.js.map +1 -1
- 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 +13 -3
- package/dist/compiler/scan.js +21 -13
- package/dist/compiler/scan.js.map +1 -1
- 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/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 +8 -12
- package/dist/define.js.map +1 -1
- package/dist/devtools-events.d.ts +8 -0
- package/dist/devtools-events.js.map +1 -1
- package/dist/devtools-off.d.ts +1 -0
- package/dist/devtools-off.js +1 -0
- package/dist/devtools-off.js.map +1 -1
- package/dist/devtools.d.ts +3 -0
- package/dist/devtools.js +14 -0
- package/dist/devtools.js.map +1 -1
- 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 +6 -2
- package/dist/element-types.js.map +1 -1
- package/dist/element.js +80 -27
- package/dist/element.js.map +1 -1
- 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 +2 -0
- package/dist/eslint/imports.js +2 -2
- package/dist/eslint/imports.js.map +1 -1
- package/dist/eslint/index.d.ts +2 -1
- package/dist/eslint/index.js +11 -3
- package/dist/eslint/index.js.map +1 -1
- package/dist/eslint/template-rule.d.ts +1 -0
- package/dist/eslint/template-rule.js +15 -5
- package/dist/eslint/template-rule.js.map +1 -1
- 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 +2 -2
- package/dist/features.js.map +1 -1
- package/dist/focus.d.ts +6 -0
- package/dist/focus.js +32 -2
- 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/host-model.d.ts +34 -5
- package/dist/host-model.js +146 -23
- package/dist/host-model.js.map +1 -1
- package/dist/hydration-client.js +2 -2
- package/dist/hydration-client.js.map +1 -1
- 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 +0 -12
- package/dist/hydration.js +3 -52
- package/dist/hydration.js.map +1 -1
- package/dist/index.d.ts +20 -24
- package/dist/index.js +10 -19
- 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 +41 -19
- package/dist/intent.js +144 -106
- 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 +12 -4
- package/dist/internal/interpreter.js +36 -48
- 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/light-dom.d.ts +1 -1
- package/dist/light-dom.js.map +1 -1
- package/dist/prop.d.ts +30 -7
- package/dist/prop.js +19 -0
- package/dist/prop.js.map +1 -1
- package/dist/props.d.ts +8 -3
- package/dist/props.js +22 -15
- 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 +7 -3
- package/dist/scheduler.js +38 -56
- package/dist/scheduler.js.map +1 -1
- 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 +1 -1
- package/dist/server-component.js +45 -14
- package/dist/server-component.js.map +1 -1
- package/dist/server.d.ts +8 -2
- package/dist/server.js +11 -2
- package/dist/server.js.map +1 -1
- package/dist/settled.d.ts +4 -3
- package/dist/settled.js +48 -26
- package/dist/settled.js.map +1 -1
- 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 -8
- 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.js +2 -2
- package/dist/store-binding.js.map +1 -1
- package/dist/store-scope.d.ts +2 -4
- package/dist/store-scope.js +6 -16
- package/dist/store-scope.js.map +1 -1
- package/dist/store.js +36 -8
- package/dist/store.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 +4 -5
- package/dist/transitions.js +10 -4
- package/dist/transitions.js.map +1 -1
- package/dist/types.d.ts +124 -27
- 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 +5 -0
- package/dist/view/attributes.js +5 -0
- package/dist/view/attributes.js.map +1 -1
- package/dist/view/compiled.d.ts +1 -1
- package/dist/view/compiled.js +1 -1
- package/dist/view/compiled.js.map +1 -1
- package/dist/view/index.d.ts +9 -4
- package/dist/view/index.js +9 -3
- package/dist/view/index.js.map +1 -1
- 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 +5 -2
- package/dist/view/normalize/check.js +6 -3
- package/dist/view/normalize/check.js.map +1 -1
- package/dist/view/normalize/emit.d.ts +2 -0
- package/dist/view/normalize/emit.js +40 -11
- package/dist/view/normalize/emit.js.map +1 -1
- package/dist/view/normalize/errors.js +1 -1
- package/dist/view/normalize/errors.js.map +1 -1
- package/dist/view/normalize/id.d.ts +5 -2
- package/dist/view/normalize/id.js +9 -2
- package/dist/view/normalize/id.js.map +1 -1
- package/dist/view/normalize/normalize.d.ts +7 -4
- package/dist/view/normalize/normalize.js +15 -9
- package/dist/view/normalize/normalize.js.map +1 -1
- package/dist/view/normalize/rules.d.ts +9 -0
- package/dist/view/normalize/rules.js +35 -5
- package/dist/view/normalize/rules.js.map +1 -1
- 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/tokens.d.ts +5 -1
- package/dist/view/normalize/tokens.js.map +1 -1
- package/dist/view/normalize/tree.d.ts +8 -2
- package/dist/view/normalize/tree.js +58 -13
- package/dist/view/normalize/tree.js.map +1 -1
- package/dist/view/normalize/types.d.ts +24 -4
- package/dist/view/normalize/types.js +4 -1
- package/dist/view/normalize/types.js.map +1 -1
- package/dist/view/normalize/whitespace.js +4 -3
- package/dist/view/normalize/whitespace.js.map +1 -1
- package/dist/view/prepare-stub.js +2 -2
- package/dist/view/prepare-stub.js.map +1 -1
- package/dist/view/prepare.d.ts +5 -2
- package/dist/view/prepare.js +9 -3
- package/dist/view/prepare.js.map +1 -1
- package/dist/view/registry.d.ts +15 -0
- package/dist/view/registry.js +10 -2
- package/dist/view/registry.js.map +1 -1
- package/dist/view/render/adopt-attr.js +7 -1
- package/dist/view/render/adopt-attr.js.map +1 -1
- package/dist/view/render/adopt.js +21 -4
- package/dist/view/render/adopt.js.map +1 -1
- package/dist/view/render/attr-parts.d.ts +12 -1
- package/dist/view/render/attr-parts.js +38 -5
- package/dist/view/render/attr-parts.js.map +1 -1
- package/dist/view/render/child-part.js +5 -2
- package/dist/view/render/child-part.js.map +1 -1
- 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 +3 -1
- package/dist/view/render/hook-part.js +21 -5
- package/dist/view/render/hook-part.js.map +1 -1
- 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 +73 -5
- package/dist/view/render/hooks.js +79 -17
- package/dist/view/render/hooks.js.map +1 -1
- package/dist/view/render/hydrate.js +2 -2
- package/dist/view/render/hydrate.js.map +1 -1
- 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/mismatch.js +5 -3
- package/dist/view/render/mismatch.js.map +1 -1
- 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/raw.d.ts +4 -1
- package/dist/view/render/raw.js +6 -2
- package/dist/view/render/raw.js.map +1 -1
- package/dist/view/render/render.d.ts +4 -1
- package/dist/view/render/render.js +17 -12
- package/dist/view/render/render.js.map +1 -1
- 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/warn.d.ts +14 -0
- package/dist/view/render/warn.js +45 -0
- package/dist/view/render/warn.js.map +1 -1
- package/dist/view/server/component.d.ts +6 -3
- package/dist/view/server/component.js +29 -7
- package/dist/view/server/component.js.map +1 -1
- package/dist/view/server/index.d.ts +20 -0
- package/dist/view/server/index.js +12 -4
- package/dist/view/server/index.js.map +1 -1
- package/dist/view/server/tags.d.ts +13 -2
- package/dist/view/server/tags.js +13 -2
- package/dist/view/server/tags.js.map +1 -1
- package/dist/view/server/values.d.ts +2 -0
- package/dist/view/server/values.js +8 -0
- package/dist/view/server/values.js.map +1 -1
- package/dist/view/server/writer.d.ts +9 -4
- package/dist/view/server/writer.js +33 -18
- package/dist/view/server/writer.js.map +1 -1
- package/dist/view/template-element.d.ts +7 -0
- package/dist/view/template-element.js +25 -5
- package/dist/view/template-element.js.map +1 -1
- package/dist/view/template.d.ts +10 -2
- package/dist/view/template.js +62 -8
- package/dist/view/template.js.map +1 -1
- 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 +38 -31
- package/dist/vite.js +198 -31
- package/dist/vite.js.map +1 -1
- package/package.json +34 -3
- package/dist/hooks/labelled-by.d.ts +0 -13
- package/dist/hooks/labelled-by.js +0 -51
- package/dist/hooks/labelled-by.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/view/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/view/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,wFAAwF;AACxF,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/view/index.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,wFAAwF;AACxF,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAoB,MAAM,cAAc,CAAC;AAC7E,OAAO,EACL,IAAI,EACJ,GAAG,EACH,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,UAAU,GAEX,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAiB,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAsB,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAWlE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAE,OAAO,EAAoD,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,UAAU,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,GAInB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,GAAG,EACH,aAAa,EACb,SAAS,EACT,UAAU,GAIX,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,qBAAqB,GAKtB,MAAM,eAAe,CAAC","sourcesContent":["// The view layer's entry point for the rest of core (ADR 0018 \"Where it lives\"): code outside\n// view/ imports only this module. @gyral/core's index re-exports the public part of it.\nexport { DEV } from '#view-dev';\nexport { codeName, docsLink, message, type MessageCode } from './message.js';\nexport {\n html,\n svg,\n compiled,\n compiledSvg,\n isTemplateResult,\n templateOf,\n type TemplateResult,\n} from './template.js';\nexport { templateElement } from './template-element.js';\nexport { normalize, analyze, type Analysis } from './normalize/normalize.js';\nexport { checkTemplate, type TemplateIssue } from './normalize/check.js';\nexport { templateId } from './normalize/id.js';\nexport { TemplateError } from './normalize/errors.js';\nexport { shapeMismatch, repairError } from './normalize/shape.js';\nexport type {\n NormalizedTemplate,\n PartSpec,\n Path,\n Segment,\n Shape,\n ShapeNode,\n TemplateObject,\n} from './normalize/types.js';\n\nexport { hydrate } from './render/hydrate.js';\nexport { render, renderBatch } from './render/render.js';\nexport type { Markup, SeenMarkup } from './render/seen.js';\nexport { HydrationMismatch } from './render/mismatch.js';\nexport { each } from './render/list.js';\nexport { keyed } from './render/keyed.js';\nexport { raw } from './render/raw.js';\nexport { nothing, type ChildValue, type ListResult, type RawResult } from './render/values.js';\nexport { defineHook } from './render/hook-part.js';\nexport { useToggles } from './render/toggles.js';\nexport { applyToggle } from './render/modal.js';\nexport { commitTracked } from './render/dispose.js';\nexport {\n flushHooks,\n onHookFailure,\n suspendHooks,\n useDisposableHooks,\n type HookAttributes,\n type HookResult,\n type HookSpec,\n} from './render/hooks.js';\nexport {\n css,\n isStyleSource,\n sheetsFor,\n styleTexts,\n type CssValue,\n type StyleSource,\n type Styles,\n} from './styles.js';\nexport {\n ERROR_ATTRIBUTE,\n ISLAND_ATTRIBUTE,\n LIGHT_ATTRIBUTE,\n SEED_ATTRIBUTE,\n} from './attributes.js';\nexport {\n registerServerComponent,\n registerServerProvider,\n serverComponent,\n serverComponents,\n serverProvider,\n serverRegistryVersion,\n type ServerComponent,\n type ServerProvider,\n type ServerRenderInput,\n type ServerRendering,\n} from './registry.js';\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** The call site recorded for a template's strings. */
|
|
2
|
+
export declare const locOf: (strings: readonly string[]) => string | undefined;
|
|
3
|
+
/** Records `loc` for `strings` unless one is known. */
|
|
4
|
+
export declare function setLoc(strings: readonly string[], loc: string | undefined): void;
|
|
5
|
+
/**
|
|
6
|
+
* `path:line:col` of the frame that called the function which created `stack` (the second
|
|
7
|
+
* frame: the first is that function itself), or undefined when the stack has none.
|
|
8
|
+
*/
|
|
9
|
+
export declare function callSite(stack: string | undefined): string | undefined;
|
package/dist/view/loc.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Development: where each runtime template was written (view/01-templates.md "Source
|
|
2
|
+
// locations", gyral-g1r.24), so TemplateError and HydrationMismatch can name `file:line:col`.
|
|
3
|
+
// Recorded once per call site (strings array): by the Vite preset's development transform
|
|
4
|
+
// (`html.at(loc)`, exact source positions), or else from a stack trace at the first `html`
|
|
5
|
+
// call. Stack positions are those of the code the browser runs: exact without a build step,
|
|
6
|
+
// shifted by any transform that doesn't keep lines. Only reached from `if (DEV)` code, so
|
|
7
|
+
// production bundles leave this module out.
|
|
8
|
+
const locs = new WeakMap();
|
|
9
|
+
/** The call site recorded for a template's strings. */
|
|
10
|
+
export const locOf = (strings) => locs.get(strings);
|
|
11
|
+
/** Records `loc` for `strings` unless one is known. */
|
|
12
|
+
export function setLoc(strings, loc) {
|
|
13
|
+
if (loc !== undefined && !locs.has(strings))
|
|
14
|
+
locs.set(strings, loc);
|
|
15
|
+
}
|
|
16
|
+
/** A frame's position: `url:line:col`. */
|
|
17
|
+
const POSITION = /^(.+):(\d+):(\d+)$/;
|
|
18
|
+
/** The `url:line:col` of a stack line: V8 `at f (…)` / `at …`, Firefox and Safari `f@…`. */
|
|
19
|
+
function frameOf(line) {
|
|
20
|
+
const text = line.trim();
|
|
21
|
+
if (text.startsWith('at ')) {
|
|
22
|
+
const rest = text.slice(3);
|
|
23
|
+
const open = rest.lastIndexOf('(');
|
|
24
|
+
return rest.endsWith(')') && open !== -1 ? rest.slice(open + 1, -1) : rest;
|
|
25
|
+
}
|
|
26
|
+
const at = text.indexOf('@');
|
|
27
|
+
return at === -1 ? undefined : text.slice(at + 1);
|
|
28
|
+
}
|
|
29
|
+
/** A frame's URL as a path: no scheme and host, query, hash, or Vite's `/@fs` prefix. */
|
|
30
|
+
const pathOf = (url) => url
|
|
31
|
+
.replace(/[?#].*$/, '')
|
|
32
|
+
.replace(/^[a-z][\w+.-]*:\/\/[^/]*/i, '')
|
|
33
|
+
.replace(/^\/@fs\//, '/');
|
|
34
|
+
/**
|
|
35
|
+
* `path:line:col` of the frame that called the function which created `stack` (the second
|
|
36
|
+
* frame: the first is that function itself), or undefined when the stack has none.
|
|
37
|
+
*/
|
|
38
|
+
export function callSite(stack) {
|
|
39
|
+
let seen = 0;
|
|
40
|
+
for (const line of (stack ?? '').split('\n')) {
|
|
41
|
+
const m = POSITION.exec(frameOf(line) ?? '');
|
|
42
|
+
if (m === null)
|
|
43
|
+
continue;
|
|
44
|
+
if (seen++ === 0)
|
|
45
|
+
continue;
|
|
46
|
+
return `${pathOf(m[1] ?? '')}:${m[2] ?? ''}:${m[3] ?? ''}`;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=loc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loc.js","sourceRoot":"","sources":["../../src/view/loc.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,8FAA8F;AAC9F,0FAA0F;AAC1F,2FAA2F;AAC3F,4FAA4F;AAC5F,0FAA0F;AAC1F,4CAA4C;AAE5C,MAAM,IAAI,GAAG,IAAI,OAAO,EAA6B,CAAC;AAEtD,uDAAuD;AACvD,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,OAA0B,EAAsB,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAE3F,uDAAuD;AACvD,MAAM,UAAU,MAAM,CAAC,OAA0B,EAAE,GAAuB;IACxE,IAAI,GAAG,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AACtE,CAAC;AAED,0CAA0C;AAC1C,MAAM,QAAQ,GAAG,oBAAoB,CAAC;AAEtC,4FAA4F;AAC5F,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7E,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,yFAAyF;AACzF,MAAM,MAAM,GAAG,CAAC,GAAW,EAAU,EAAE,CACrC,GAAG;KACA,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC;KACtB,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC;KACxC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAE9B;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAyB;IAChD,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,IAAI;YAAE,SAAS;QACzB,IAAI,IAAI,EAAE,KAAK,CAAC;YAAE,SAAS;QAC3B,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;IAC7D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["// Development: where each runtime template was written (view/01-templates.md \"Source\n// locations\", gyral-g1r.24), so TemplateError and HydrationMismatch can name `file:line:col`.\n// Recorded once per call site (strings array): by the Vite preset's development transform\n// (`html.at(loc)`, exact source positions), or else from a stack trace at the first `html`\n// call. Stack positions are those of the code the browser runs: exact without a build step,\n// shifted by any transform that doesn't keep lines. Only reached from `if (DEV)` code, so\n// production bundles leave this module out.\n\nconst locs = new WeakMap<readonly string[], string>();\n\n/** The call site recorded for a template's strings. */\nexport const locOf = (strings: readonly string[]): string | undefined => locs.get(strings);\n\n/** Records `loc` for `strings` unless one is known. */\nexport function setLoc(strings: readonly string[], loc: string | undefined): void {\n if (loc !== undefined && !locs.has(strings)) locs.set(strings, loc);\n}\n\n/** A frame's position: `url:line:col`. */\nconst POSITION = /^(.+):(\\d+):(\\d+)$/;\n\n/** The `url:line:col` of a stack line: V8 `at f (…)` / `at …`, Firefox and Safari `f@…`. */\nfunction frameOf(line: string): string | undefined {\n const text = line.trim();\n if (text.startsWith('at ')) {\n const rest = text.slice(3);\n const open = rest.lastIndexOf('(');\n return rest.endsWith(')') && open !== -1 ? rest.slice(open + 1, -1) : rest;\n }\n const at = text.indexOf('@');\n return at === -1 ? undefined : text.slice(at + 1);\n}\n\n/** A frame's URL as a path: no scheme and host, query, hash, or Vite's `/@fs` prefix. */\nconst pathOf = (url: string): string =>\n url\n .replace(/[?#].*$/, '')\n .replace(/^[a-z][\\w+.-]*:\\/\\/[^/]*/i, '')\n .replace(/^\\/@fs\\//, '/');\n\n/**\n * `path:line:col` of the frame that called the function which created `stack` (the second\n * frame: the first is that function itself), or undefined when the stack has none.\n */\nexport function callSite(stack: string | undefined): string | undefined {\n let seen = 0;\n for (const line of (stack ?? '').split('\\n')) {\n const m = POSITION.exec(frameOf(line) ?? '');\n if (m === null) continue;\n if (seen++ === 0) continue;\n return `${pathOf(m[1] ?? '')}:${m[2] ?? ''}:${m[3] ?? ''}`;\n }\n return undefined;\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { MESSAGES } from './messages.js';
|
|
2
|
+
/** A diagnostic's code (messages.ts). */
|
|
3
|
+
export type MessageCode = keyof typeof MESSAGES;
|
|
4
|
+
/** Where production messages point: the docs page generated from messages.ts. */
|
|
5
|
+
export declare const ERRORS_URL = "https://gyral.dev/errors/#";
|
|
6
|
+
/** `G0010` for code 10. */
|
|
7
|
+
export declare const codeName: (code: number) => string;
|
|
8
|
+
/**
|
|
9
|
+
* `Gyral G0062 https://gyral.dev/errors/#G0062`, for a message that keeps a sentence of its own
|
|
10
|
+
* in production (a hydration mismatch names the node in words) and points to the docs there.
|
|
11
|
+
*/
|
|
12
|
+
export declare const docsLink: (code: MessageCode) => string;
|
|
13
|
+
/**
|
|
14
|
+
* The text of diagnostic `code` with its arguments: in development the full message, in
|
|
15
|
+
* production `Gyral G0010 <args…> https://gyral.dev/errors/#G0010`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function message(code: MessageCode, ...args: readonly unknown[]): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Diagnostic text (gyral-c5d.13): the full message in development, a code and the docs URL in
|
|
2
|
+
// production, so production bundles carry no message table. Every error and warning core can
|
|
3
|
+
// raise in production goes through `message()` (or, for a hydration mismatch, which keeps its
|
|
4
|
+
// sentence, `docsLink()`); development-only checks keep their own text behind `DEV`. The codes
|
|
5
|
+
// and texts are in messages.ts.
|
|
6
|
+
import { DEV } from '#view-dev';
|
|
7
|
+
import { MESSAGES } from './messages.js';
|
|
8
|
+
/** Where production messages point: the docs page generated from messages.ts. */
|
|
9
|
+
export const ERRORS_URL = 'https://gyral.dev/errors/#';
|
|
10
|
+
/** `G0010` for code 10. */
|
|
11
|
+
export const codeName = (code) => `G${String(code).padStart(4, '0')}`;
|
|
12
|
+
/** Development: the table's text with `args` in its placeholders. */
|
|
13
|
+
function fullText(code, args) {
|
|
14
|
+
const names = [];
|
|
15
|
+
return MESSAGES[code].replace(/\{(\w+)\}/g, (_, name) => {
|
|
16
|
+
let at = names.indexOf(name);
|
|
17
|
+
if (at < 0)
|
|
18
|
+
at = names.push(name) - 1;
|
|
19
|
+
return String(args[at]);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* `Gyral G0062 https://gyral.dev/errors/#G0062`, for a message that keeps a sentence of its own
|
|
24
|
+
* in production (a hydration mismatch names the node in words) and points to the docs there.
|
|
25
|
+
*/
|
|
26
|
+
export const docsLink = (code) => {
|
|
27
|
+
const id = codeName(code);
|
|
28
|
+
return `Gyral ${id} ${ERRORS_URL}${id}`;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* The text of diagnostic `code` with its arguments: in development the full message, in
|
|
32
|
+
* production `Gyral G0010 <args…> https://gyral.dev/errors/#G0010`.
|
|
33
|
+
*/
|
|
34
|
+
export function message(code, ...args) {
|
|
35
|
+
if (DEV)
|
|
36
|
+
return fullText(code, args);
|
|
37
|
+
const id = codeName(code);
|
|
38
|
+
return [`Gyral ${id}`, ...args, ERRORS_URL + id].join(' ');
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/view/message.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,6FAA6F;AAC7F,8FAA8F;AAC9F,+FAA+F;AAC/F,gCAAgC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC,iFAAiF;AACjF,MAAM,CAAC,MAAM,UAAU,GAAG,4BAA4B,CAAC;AAEvD,2BAA2B;AAC3B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;AAEtF,qEAAqE;AACrE,SAAS,QAAQ,CAAC,IAAiB,EAAE,IAAwB;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE;QAC9D,IAAI,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,EAAE,GAAG,CAAC;YAAE,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAiB,EAAU,EAAE;IACpD,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,SAAS,EAAE,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;AAC1C,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,IAAiB,EAAE,GAAG,IAAwB;IACpE,IAAI,GAAG;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,CAAC","sourcesContent":["// Diagnostic text (gyral-c5d.13): the full message in development, a code and the docs URL in\n// production, so production bundles carry no message table. Every error and warning core can\n// raise in production goes through `message()` (or, for a hydration mismatch, which keeps its\n// sentence, `docsLink()`); development-only checks keep their own text behind `DEV`. The codes\n// and texts are in messages.ts.\nimport { DEV } from '#view-dev';\nimport { MESSAGES } from './messages.js';\n\n/** A diagnostic's code (messages.ts). */\nexport type MessageCode = keyof typeof MESSAGES;\n\n/** Where production messages point: the docs page generated from messages.ts. */\nexport const ERRORS_URL = 'https://gyral.dev/errors/#';\n\n/** `G0010` for code 10. */\nexport const codeName = (code: number): string => `G${String(code).padStart(4, '0')}`;\n\n/** Development: the table's text with `args` in its placeholders. */\nfunction fullText(code: MessageCode, args: readonly unknown[]): string {\n const names: string[] = [];\n return MESSAGES[code].replace(/\\{(\\w+)\\}/g, (_, name: string) => {\n let at = names.indexOf(name);\n if (at < 0) at = names.push(name) - 1;\n return String(args[at]);\n });\n}\n\n/**\n * `Gyral G0062 https://gyral.dev/errors/#G0062`, for a message that keeps a sentence of its own\n * in production (a hydration mismatch names the node in words) and points to the docs there.\n */\nexport const docsLink = (code: MessageCode): string => {\n const id = codeName(code);\n return `Gyral ${id} ${ERRORS_URL}${id}`;\n};\n\n/**\n * The text of diagnostic `code` with its arguments: in development the full message, in\n * production `Gyral G0010 <args…> https://gyral.dev/errors/#G0010`.\n */\nexport function message(code: MessageCode, ...args: readonly unknown[]): string {\n if (DEV) return fullText(code, args);\n const id = codeName(code);\n return [`Gyral ${id}`, ...args, ERRORS_URL + id].join(' ');\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const MESSAGES: {
|
|
2
|
+
readonly 1: "<{tag}> is a browser element (render it on the server with @gyral/ssr).";
|
|
3
|
+
readonly 10: "<{tag}> has no update for message \"{message}\".";
|
|
4
|
+
readonly 11: "<{tag}> has no intent parser for data-intent=\"{intent}\".";
|
|
5
|
+
readonly 12: "<{tag}> intent parser for \"{intent}\" failed";
|
|
6
|
+
readonly 13: "<{tag}> focus(\"{selector}\") matched no focusable element.";
|
|
7
|
+
readonly 20: "<{tag}> prop \"{prop}\" has an asynchronous schema; it must be synchronous.";
|
|
8
|
+
readonly 21: "<{tag}> prop \"{prop}\" got an invalid value from {source}, so it is treated as missing: {issues}";
|
|
9
|
+
readonly 22: "<{tag}> is missing required prop(s): {props}.";
|
|
10
|
+
readonly 23: string;
|
|
11
|
+
readonly 30: "gyral: a deferred callback failed";
|
|
12
|
+
readonly 31: "<{tag}> view failed; it shows its error view, or its previous DOM stays.";
|
|
13
|
+
readonly 32: "gyral: post-render work failed";
|
|
14
|
+
readonly 33: string;
|
|
15
|
+
readonly 34: string;
|
|
16
|
+
readonly 40: "{owner}: the onSuccess or onFailure mapper for driver \"{driver}\" threw; no message was sent.";
|
|
17
|
+
readonly 41: "{owner}: driver \"{driver}\" failed and the command has no onFailure.";
|
|
18
|
+
readonly 42: "gyral: subscription \"{name}\" failed to unsubscribe";
|
|
19
|
+
readonly 43: string;
|
|
20
|
+
readonly 50: string;
|
|
21
|
+
readonly 51: "store \"{store}\": the server's seed failed its schema, so it starts from init. Issues: {issues}";
|
|
22
|
+
readonly 52: "unreadable {attribute} seed on {where}";
|
|
23
|
+
readonly 53: string;
|
|
24
|
+
readonly 54: string;
|
|
25
|
+
readonly 55: "store \"{store}\" has no update for message \"{message}\".";
|
|
26
|
+
readonly 60: "<{tag}> has an unreadable {attribute}";
|
|
27
|
+
readonly 61: "gyral: hydration code failed to load; rendering fresh";
|
|
28
|
+
readonly 62: string;
|
|
29
|
+
readonly 63: "<{tag}> was rendered fresh after a hydration mismatch:";
|
|
30
|
+
readonly 70: string;
|
|
31
|
+
readonly 71: "gyral: template rule 11: a page shell rendered in the browser.";
|
|
32
|
+
readonly 72: string;
|
|
33
|
+
readonly 73: "<{tag}> update for \"{message}\" failed; the state is unchanged.";
|
|
34
|
+
readonly 74: "<{tag}> init failed; it shows its error view, or stays empty.";
|
|
35
|
+
readonly 75: "<{tag}> element hook failed; the other hooks still ran.";
|
|
36
|
+
readonly 76: "store \"{store}\": update for \"{message}\" failed; the state is unchanged.";
|
|
37
|
+
readonly 77: "store \"{store}\": a subscriber failed; the other subscribers were still notified.";
|
|
38
|
+
readonly 78: string;
|
|
39
|
+
readonly 79: string;
|
|
40
|
+
readonly 80: string;
|
|
41
|
+
readonly 85: "<{tag}> call(\"{selector}\", \"{method}\") failed";
|
|
42
|
+
readonly 86: "call(\"{selector}\", \"{method}\"): arguments must be plain data.";
|
|
43
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Core's diagnostics, by code (gyral-c5d.13, docs/references/errors.md). Development
|
|
2
|
+
// builds print the full text, production builds `Gyral G0010 <arguments…> <docs URL>`
|
|
3
|
+
// (message.ts), so this table stays out of production bundles. `{name}` placeholders take the
|
|
4
|
+
// call's arguments in order of first appearance; a name used twice repeats its argument.
|
|
5
|
+
// docs/references/errors.md and errors.json are generated from this table (`node
|
|
6
|
+
// scripts/errors.mjs`); `pnpm invariants` checks that they are current, that codes are unique
|
|
7
|
+
// and that every `message(code, …)` call names a code here with as many arguments as its text
|
|
8
|
+
// has placeholders (`docsLink(code)` marks a message that keeps its own sentence in
|
|
9
|
+
// production). Codes are never reused: a retired message keeps its code out of use.
|
|
10
|
+
// Plain data, no TypeScript beyond `as const`, so Node scripts import it as is.
|
|
11
|
+
export const MESSAGES = {
|
|
12
|
+
// Components
|
|
13
|
+
1: '<{tag}> is a browser element (render it on the server with @gyral/ssr).',
|
|
14
|
+
10: '<{tag}> has no update for message "{message}".',
|
|
15
|
+
11: '<{tag}> has no intent parser for data-intent="{intent}".',
|
|
16
|
+
12: '<{tag}> intent parser for "{intent}" failed',
|
|
17
|
+
13: '<{tag}> focus("{selector}") matched no focusable element.',
|
|
18
|
+
// Props
|
|
19
|
+
20: '<{tag}> prop "{prop}" has an asynchronous schema; it must be synchronous.',
|
|
20
|
+
21: '<{tag}> prop "{prop}" got an invalid value from {source}, so it is treated as missing: {issues}',
|
|
21
|
+
22: '<{tag}> is missing required prop(s): {props}.',
|
|
22
|
+
23: '<{tag}> declares prop(s) that shadow built-in element properties: {props}. Setting them ' +
|
|
23
|
+
'changes platform behaviour (a prop named "hidden" hides the element). Rename them ' +
|
|
24
|
+
'(view/05-element.md).',
|
|
25
|
+
// Scheduling
|
|
26
|
+
30: 'gyral: a deferred callback failed',
|
|
27
|
+
31: '<{tag}> view failed; it shows its error view, or its previous DOM stays.',
|
|
28
|
+
32: 'gyral: post-render work failed',
|
|
29
|
+
33: 'gyral: rendering did not settle in one flush (a cycle between {tags}). Components are ' +
|
|
30
|
+
'probably feeding each other props or messages; break the cycle with a condition in update ' +
|
|
31
|
+
'(docs/design-docs/view/04-scheduler.md "Loop guard").',
|
|
32
|
+
34: 'settled(): the page did not settle after {rounds} flushes or busy turns. A stream is ' +
|
|
33
|
+
'emitting without pause, or components (or drivers) are feeding each other messages in a ' +
|
|
34
|
+
'cycle.',
|
|
35
|
+
// Commands
|
|
36
|
+
40: '{owner}: the onSuccess or onFailure mapper for driver "{driver}" threw; no message was sent.',
|
|
37
|
+
41: '{owner}: driver "{driver}" failed and the command has no onFailure.',
|
|
38
|
+
42: 'gyral: subscription "{name}" failed to unsubscribe',
|
|
39
|
+
43: '{owner}: no driver provides "{driver}". It is a driver token: provide an implementation ' +
|
|
40
|
+
'by name with provideDrivers(root, { {driver}: … }) or el.drivers (ADR 0006 "Driver tokens").',
|
|
41
|
+
// Stores
|
|
42
|
+
50: '<{tag}> uses store "{store}" without declaring it. Add it to the spec: stores: [{store}] ' +
|
|
43
|
+
'(ADR 0013), so the component subscribes to its changes.',
|
|
44
|
+
51: 'store "{store}": the server\'s seed failed its schema, so it starts from init. Issues: {issues}',
|
|
45
|
+
52: 'unreadable {attribute} seed on {where}',
|
|
46
|
+
53: '<{tag}> reads store "{store}" during a server render without a store scope. Pass the ' +
|
|
47
|
+
"request's store instances to renderPage({ stores }) or renderToString(value, { stores }).",
|
|
48
|
+
54: 'store "{store}" sends to "{target}" but is not held by a store scope (a registry, ' +
|
|
49
|
+
'<gyral-stores> or the page default), so the message is dropped.',
|
|
50
|
+
55: 'store "{store}" has no update for message "{message}".',
|
|
51
|
+
// Hydration
|
|
52
|
+
60: '<{tag}> has an unreadable {attribute}',
|
|
53
|
+
61: 'gyral: hydration code failed to load; rendering fresh',
|
|
54
|
+
62: "gyral: hydration mismatch in {host} at {path}: expected {expected}, found {found}. The server's " +
|
|
55
|
+
"HTML differs from the first client render: a view that isn't deterministic (Date.now(), " +
|
|
56
|
+
'locale), a third party that changed the DOM before scripts ran, or a stale cached page ' +
|
|
57
|
+
'(docs/design-docs/view/07-hydration.md "Mismatches").',
|
|
58
|
+
63: '<{tag}> was rendered fresh after a hydration mismatch:',
|
|
59
|
+
// Templates
|
|
60
|
+
70: 'gyral: an html template was not compiled: `{start}`. Under the gyral-compiled condition ' +
|
|
61
|
+
'every html`…` must be compiled by the Gyral Vite preset (view/01-templates.md).',
|
|
62
|
+
71: 'gyral: template rule 11: a page shell rendered in the browser.',
|
|
63
|
+
72: 'gyral: this page\'s Trusted Types policy list does not allow the policy "gyral", so ' +
|
|
64
|
+
'templates are parsed from plain strings, which works only while Trusted Types are not ' +
|
|
65
|
+
'enforced. Add `trusted-types gyral` to the Content-Security-Policy.',
|
|
66
|
+
// Errors (ADR 0024)
|
|
67
|
+
73: '<{tag}> update for "{message}" failed; the state is unchanged.',
|
|
68
|
+
74: '<{tag}> init failed; it shows its error view, or stays empty.',
|
|
69
|
+
75: '<{tag}> element hook failed; the other hooks still ran.',
|
|
70
|
+
76: 'store "{store}": update for "{message}" failed; the state is unchanged.',
|
|
71
|
+
77: 'store "{store}": a subscriber failed; the other subscribers were still notified.',
|
|
72
|
+
78: '<{tag}> failed to render on the server; it renders its error view (or nothing) and ' +
|
|
73
|
+
'starts fresh in the browser.',
|
|
74
|
+
// Subscriptions (ADR 0025)
|
|
75
|
+
79: '<{tag}> subscriptions returned two commands for lane "{lane}"; only the first runs. ' +
|
|
76
|
+
'Give each its own `key`.',
|
|
77
|
+
80: "<{tag}> subscriptions kept restarting: a subscription's input data changes with every " +
|
|
78
|
+
'message it sends (for example a timestamp or a counter in the input). Keep inputs to what ' +
|
|
79
|
+
'should restart it; functions are ignored, so to restart on a new selector, change the key.',
|
|
80
|
+
// Element calls (gyral-1zd.27)
|
|
81
|
+
85: '<{tag}> call("{selector}", "{method}") failed',
|
|
82
|
+
86: 'call("{selector}", "{method}"): arguments must be plain data.',
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/view/messages.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,sFAAsF;AACtF,8FAA8F;AAC9F,yFAAyF;AACzF,iFAAiF;AACjF,8FAA8F;AAC9F,8FAA8F;AAC9F,oFAAoF;AACpF,oFAAoF;AACpF,gFAAgF;AAChF,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,aAAa;IACb,CAAC,EAAE,yEAAyE;IAC5E,EAAE,EAAE,gDAAgD;IACpD,EAAE,EAAE,0DAA0D;IAC9D,EAAE,EAAE,6CAA6C;IACjD,EAAE,EAAE,2DAA2D;IAC/D,QAAQ;IACR,EAAE,EAAE,2EAA2E;IAC/E,EAAE,EAAE,iGAAiG;IACrG,EAAE,EAAE,+CAA+C;IACnD,EAAE,EACA,0FAA0F;QAC1F,oFAAoF;QACpF,uBAAuB;IACzB,aAAa;IACb,EAAE,EAAE,mCAAmC;IACvC,EAAE,EAAE,0EAA0E;IAC9E,EAAE,EAAE,gCAAgC;IACpC,EAAE,EACA,wFAAwF;QACxF,4FAA4F;QAC5F,uDAAuD;IACzD,EAAE,EACA,uFAAuF;QACvF,0FAA0F;QAC1F,QAAQ;IACV,WAAW;IACX,EAAE,EAAE,8FAA8F;IAClG,EAAE,EAAE,qEAAqE;IACzE,EAAE,EAAE,oDAAoD;IACxD,EAAE,EACA,0FAA0F;QAC1F,8FAA8F;IAChG,SAAS;IACT,EAAE,EACA,2FAA2F;QAC3F,yDAAyD;IAC3D,EAAE,EAAE,iGAAiG;IACrG,EAAE,EAAE,wCAAwC;IAC5C,EAAE,EACA,uFAAuF;QACvF,2FAA2F;IAC7F,EAAE,EACA,oFAAoF;QACpF,iEAAiE;IACnE,EAAE,EAAE,wDAAwD;IAC5D,YAAY;IACZ,EAAE,EAAE,uCAAuC;IAC3C,EAAE,EAAE,uDAAuD;IAC3D,EAAE,EACA,kGAAkG;QAClG,0FAA0F;QAC1F,yFAAyF;QACzF,uDAAuD;IACzD,EAAE,EAAE,wDAAwD;IAC5D,YAAY;IACZ,EAAE,EACA,0FAA0F;QAC1F,iFAAiF;IACnF,EAAE,EAAE,gEAAgE;IACpE,EAAE,EACA,sFAAsF;QACtF,wFAAwF;QACxF,qEAAqE;IACvE,oBAAoB;IACpB,EAAE,EAAE,gEAAgE;IACpE,EAAE,EAAE,+DAA+D;IACnE,EAAE,EAAE,yDAAyD;IAC7D,EAAE,EAAE,yEAAyE;IAC7E,EAAE,EAAE,kFAAkF;IACtF,EAAE,EACA,qFAAqF;QACrF,8BAA8B;IAChC,2BAA2B;IAC3B,EAAE,EACA,sFAAsF;QACtF,0BAA0B;IAC5B,EAAE,EACA,wFAAwF;QACxF,4FAA4F;QAC5F,4FAA4F;IAC9F,+BAA+B;IAC/B,EAAE,EAAE,+CAA+C;IACnD,EAAE,EAAE,+DAA+D;CAC3D,CAAC","sourcesContent":["// Core's diagnostics, by code (gyral-c5d.13, docs/references/errors.md). Development\n// builds print the full text, production builds `Gyral G0010 <arguments…> <docs URL>`\n// (message.ts), so this table stays out of production bundles. `{name}` placeholders take the\n// call's arguments in order of first appearance; a name used twice repeats its argument.\n// docs/references/errors.md and errors.json are generated from this table (`node\n// scripts/errors.mjs`); `pnpm invariants` checks that they are current, that codes are unique\n// and that every `message(code, …)` call names a code here with as many arguments as its text\n// has placeholders (`docsLink(code)` marks a message that keeps its own sentence in\n// production). Codes are never reused: a retired message keeps its code out of use.\n// Plain data, no TypeScript beyond `as const`, so Node scripts import it as is.\nexport const MESSAGES = {\n // Components\n 1: '<{tag}> is a browser element (render it on the server with @gyral/ssr).',\n 10: '<{tag}> has no update for message \"{message}\".',\n 11: '<{tag}> has no intent parser for data-intent=\"{intent}\".',\n 12: '<{tag}> intent parser for \"{intent}\" failed',\n 13: '<{tag}> focus(\"{selector}\") matched no focusable element.',\n // Props\n 20: '<{tag}> prop \"{prop}\" has an asynchronous schema; it must be synchronous.',\n 21: '<{tag}> prop \"{prop}\" got an invalid value from {source}, so it is treated as missing: {issues}',\n 22: '<{tag}> is missing required prop(s): {props}.',\n 23:\n '<{tag}> declares prop(s) that shadow built-in element properties: {props}. Setting them ' +\n 'changes platform behaviour (a prop named \"hidden\" hides the element). Rename them ' +\n '(view/05-element.md).',\n // Scheduling\n 30: 'gyral: a deferred callback failed',\n 31: '<{tag}> view failed; it shows its error view, or its previous DOM stays.',\n 32: 'gyral: post-render work failed',\n 33:\n 'gyral: rendering did not settle in one flush (a cycle between {tags}). Components are ' +\n 'probably feeding each other props or messages; break the cycle with a condition in update ' +\n '(docs/design-docs/view/04-scheduler.md \"Loop guard\").',\n 34:\n 'settled(): the page did not settle after {rounds} flushes or busy turns. A stream is ' +\n 'emitting without pause, or components (or drivers) are feeding each other messages in a ' +\n 'cycle.',\n // Commands\n 40: '{owner}: the onSuccess or onFailure mapper for driver \"{driver}\" threw; no message was sent.',\n 41: '{owner}: driver \"{driver}\" failed and the command has no onFailure.',\n 42: 'gyral: subscription \"{name}\" failed to unsubscribe',\n 43:\n '{owner}: no driver provides \"{driver}\". It is a driver token: provide an implementation ' +\n 'by name with provideDrivers(root, { {driver}: … }) or el.drivers (ADR 0006 \"Driver tokens\").',\n // Stores\n 50:\n '<{tag}> uses store \"{store}\" without declaring it. Add it to the spec: stores: [{store}] ' +\n '(ADR 0013), so the component subscribes to its changes.',\n 51: 'store \"{store}\": the server\\'s seed failed its schema, so it starts from init. Issues: {issues}',\n 52: 'unreadable {attribute} seed on {where}',\n 53:\n '<{tag}> reads store \"{store}\" during a server render without a store scope. Pass the ' +\n \"request's store instances to renderPage({ stores }) or renderToString(value, { stores }).\",\n 54:\n 'store \"{store}\" sends to \"{target}\" but is not held by a store scope (a registry, ' +\n '<gyral-stores> or the page default), so the message is dropped.',\n 55: 'store \"{store}\" has no update for message \"{message}\".',\n // Hydration\n 60: '<{tag}> has an unreadable {attribute}',\n 61: 'gyral: hydration code failed to load; rendering fresh',\n 62:\n \"gyral: hydration mismatch in {host} at {path}: expected {expected}, found {found}. The server's \" +\n \"HTML differs from the first client render: a view that isn't deterministic (Date.now(), \" +\n 'locale), a third party that changed the DOM before scripts ran, or a stale cached page ' +\n '(docs/design-docs/view/07-hydration.md \"Mismatches\").',\n 63: '<{tag}> was rendered fresh after a hydration mismatch:',\n // Templates\n 70:\n 'gyral: an html template was not compiled: `{start}`. Under the gyral-compiled condition ' +\n 'every html`…` must be compiled by the Gyral Vite preset (view/01-templates.md).',\n 71: 'gyral: template rule 11: a page shell rendered in the browser.',\n 72:\n 'gyral: this page\\'s Trusted Types policy list does not allow the policy \"gyral\", so ' +\n 'templates are parsed from plain strings, which works only while Trusted Types are not ' +\n 'enforced. Add `trusted-types gyral` to the Content-Security-Policy.',\n // Errors (ADR 0024)\n 73: '<{tag}> update for \"{message}\" failed; the state is unchanged.',\n 74: '<{tag}> init failed; it shows its error view, or stays empty.',\n 75: '<{tag}> element hook failed; the other hooks still ran.',\n 76: 'store \"{store}\": update for \"{message}\" failed; the state is unchanged.',\n 77: 'store \"{store}\": a subscriber failed; the other subscribers were still notified.',\n 78:\n '<{tag}> failed to render on the server; it renders its error view (or nothing) and ' +\n 'starts fresh in the browser.',\n // Subscriptions (ADR 0025)\n 79:\n '<{tag}> subscriptions returned two commands for lane \"{lane}\"; only the first runs. ' +\n 'Give each its own `key`.',\n 80:\n \"<{tag}> subscriptions kept restarting: a subscription's input data changes with every \" +\n 'message it sends (for example a timestamp or a counter in the input). Keep inputs to what ' +\n 'should restart it; functions are ignored, so to restart on a new selector, change the key.',\n // Element calls (gyral-1zd.27)\n 85: '<{tag}> call(\"{selector}\", \"{method}\") failed',\n 86: 'call(\"{selector}\", \"{method}\"): arguments must be plain data.',\n} as const;\n"]}
|
|
@@ -16,5 +16,8 @@ export interface TemplateIssue {
|
|
|
16
16
|
*/
|
|
17
17
|
readonly from: At | undefined;
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The template's first rule violation, or undefined when `normalize` would accept it. `svg`: an
|
|
21
|
+
* svg template's strings (`` svg`…` ``).
|
|
22
|
+
*/
|
|
23
|
+
export declare function checkTemplate(strings: readonly string[], svg?: boolean): TemplateIssue | undefined;
|
|
@@ -60,11 +60,14 @@ class Tracker {
|
|
|
60
60
|
this.after();
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
/**
|
|
64
|
-
|
|
63
|
+
/**
|
|
64
|
+
* The template's first rule violation, or undefined when `normalize` would accept it. `svg`: an
|
|
65
|
+
* svg template's strings (`` svg`…` ``).
|
|
66
|
+
*/
|
|
67
|
+
export function checkTemplate(strings, svg = false) {
|
|
65
68
|
const normalized = minifyStrings(strings);
|
|
66
69
|
const src = new Source(normalized, undefined);
|
|
67
|
-
const tracker = new Tracker(src, new TreeBuilder(src));
|
|
70
|
+
const tracker = new Tracker(src, new TreeBuilder(src, svg));
|
|
68
71
|
try {
|
|
69
72
|
tokenize(src, tracker);
|
|
70
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/view/normalize/check.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,2FAA2F;AAC3F,8FAA8F;AAC9F,gGAAgG;AAChG,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAA8C,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAqBhD,wFAAwF;AACxF,MAAM,OAAO;IAIX,YACmB,GAAW,EACX,IAAiB;QADjB,QAAG,GAAH,GAAG,CAAQ;QACX,SAAI,GAAJ,IAAI,CAAa;QALpC,SAAI,GAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAMf,CAAC;IAEJ,8FAA8F;IACtF,MAAM,CAAC,KAAK,GAAG,IAAI;QACzB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5C,CAAC;IAEO,KAAK;QACX,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,GAAW;QACd,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,OAAO,CAAC,GAAW;QACjB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,OAAO,CAAC,GAAW;QACjB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,KAAK,CAAC,GAAa;QACjB,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IACD,GAAG,CAAC,IAAY;QACd,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,IAAI,CAAC,IAAsB;QACzB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,MAAM;QACJ,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;CACF;AAED
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../../src/view/normalize/check.ts"],"names":[],"mappings":"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","sourcesContent":["// The template rules (view/09-template-rules.md) as a check that reports where it stopped, for\n// tools that point at the markup (the ESLint plugin, @gyral/core/eslint). It runs the same\n// steps as `analyze` (normalize.ts) up to the last one that can fail: minify whitespace, then\n// tokenize and build the tree (emit and the id never throw). Like the compiler and the runtime,\n// it stops at a template's first error: the tokenizer can't recover from one.\nimport { TemplateError } from './errors.js';\nimport { Source } from './source.js';\nimport { tokenize, type ContentMode, type Sink, type StartTag } from './tokenizer.js';\nimport { TreeBuilder } from './tree.js';\nimport { minifyStrings } from './whitespace.js';\n\n/** A position in the minified strings: string index, offset in that string. */\nexport type At = readonly [index: number, offset: number];\n\n/** A template's first rule violation, and where the normalizer was when it found it. */\nexport interface TemplateIssue {\n /** The same error `normalize(strings)` throws. */\n readonly error: TemplateError;\n /** The whitespace-minified strings the rules read (as many as the input). */\n readonly strings: readonly string[];\n /** Where reading stopped. */\n readonly at: At;\n /**\n * Where the token the error is about starts, when the tree builder found it in a tag, an end\n * tag or a run of text (the token ends at `at`). Undefined when the tokenizer found it at\n * `at` itself, or at a child hole (then `at` is the end of the string before the hole).\n */\n readonly from: At | undefined;\n}\n\n/** Forwards tokens to the tree builder, remembering where the current token started. */\nclass Tracker implements Sink {\n mark: At = [0, 0];\n from: At | undefined;\n\n constructor(\n private readonly src: Source,\n private readonly tree: TreeBuilder,\n ) {}\n\n /** A token starts at `mark`; an error before `after` is about it (a child hole: the hole). */\n private before(about = true): void {\n this.from = about ? this.mark : undefined;\n }\n\n private after(): void {\n this.from = undefined;\n this.mark = [this.src.i, this.src.pos];\n }\n\n text(raw: string): void {\n this.before();\n this.tree.text(raw);\n this.after();\n }\n comment(raw: string): void {\n this.before();\n this.tree.comment(raw);\n this.after();\n }\n doctype(raw: string): void {\n this.before();\n this.tree.doctype(raw);\n this.after();\n }\n start(tag: StartTag): ContentMode {\n this.before();\n const mode = this.tree.start(tag);\n this.after();\n return mode;\n }\n end(name: string): void {\n this.before();\n this.tree.end(name);\n this.after();\n }\n hole(kind: 'child' | 'text'): void {\n this.before(false);\n this.tree.hole(kind);\n this.after();\n }\n finish(): void {\n this.before();\n this.tree.finish();\n this.after();\n }\n}\n\n/**\n * The template's first rule violation, or undefined when `normalize` would accept it. `svg`: an\n * svg template's strings (`` svg`…` ``).\n */\nexport function checkTemplate(strings: readonly string[], svg = false): TemplateIssue | undefined {\n const normalized = minifyStrings(strings);\n const src = new Source(normalized, undefined);\n const tracker = new Tracker(src, new TreeBuilder(src, svg));\n try {\n tokenize(src, tracker);\n } catch (error) {\n if (!(error instanceof TemplateError)) throw error;\n return { error, strings: normalized, at: [src.i, src.pos], from: tracker.from };\n }\n return undefined;\n}\n"]}
|
|
@@ -5,6 +5,8 @@ export interface Emitted {
|
|
|
5
5
|
readonly parts: PartSpec[];
|
|
6
6
|
readonly segments: Segment[];
|
|
7
7
|
readonly shape: Shape;
|
|
8
|
+
/** The decoded values of the template's non-empty static `style` attributes (types.ts). */
|
|
9
|
+
readonly staticStyles: string[];
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* Emits the HTML, part table, segments and shape for a template's tree. A `server` template
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
// Emits the template object's markup from the normalizer's tree (view/01-templates.md steps 3
|
|
2
|
+
// and 4): the client HTML (bound attributes and static `style` attributes removed, anchors
|
|
3
|
+
// added by view/02-bindings.md's anchor rule), the server segments (types.ts), the part table
|
|
4
|
+
// with child-index paths, and the shape of the DOM the browser must build (prepare.ts).
|
|
5
|
+
import { SVG_HTML_POINT } from './svg.js';
|
|
1
6
|
import { ATTR_PART, BOOL_PART, CHILD_BEFORE, CHILD_END, CHILD_SOLE, HOOK_PART, MULTI_PART, PROP_PART, TEXT_PART, } from './types.js';
|
|
2
7
|
const ANCHOR = '<!---->';
|
|
3
8
|
class Emitter {
|
|
@@ -7,12 +12,17 @@ class Emitter {
|
|
|
7
12
|
this.html = '';
|
|
8
13
|
this.parts = [];
|
|
9
14
|
this.segments = [];
|
|
15
|
+
this.staticStyles = [];
|
|
10
16
|
}
|
|
11
17
|
/** Static markup: appended to the HTML and to the last string segment. */
|
|
12
18
|
out(text) {
|
|
19
|
+
this.html += text;
|
|
20
|
+
this.serverOut(text);
|
|
21
|
+
}
|
|
22
|
+
/** Static markup only the server writes: appended to the last string segment. */
|
|
23
|
+
serverOut(text) {
|
|
13
24
|
if (text === '')
|
|
14
25
|
return;
|
|
15
|
-
this.html += text;
|
|
16
26
|
const last = this.segments.length - 1;
|
|
17
27
|
const prev = this.segments[last];
|
|
18
28
|
if (typeof prev === 'string')
|
|
@@ -23,7 +33,7 @@ class Emitter {
|
|
|
23
33
|
op(segment) {
|
|
24
34
|
this.segments.push(segment);
|
|
25
35
|
}
|
|
26
|
-
/** `parent`: the parent element
|
|
36
|
+
/** `parent`: the parent element; undefined at the template root. */
|
|
27
37
|
children(nodes, path, parent) {
|
|
28
38
|
const shape = [];
|
|
29
39
|
nodes.forEach((node, k) => {
|
|
@@ -57,7 +67,13 @@ class Emitter {
|
|
|
57
67
|
/** A child hole: inserts before the next static element or comment, the end, or an anchor. */
|
|
58
68
|
child(nodes, k, path, shape, parent) {
|
|
59
69
|
const next = nodes[k + 1];
|
|
60
|
-
|
|
70
|
+
if (parent === undefined)
|
|
71
|
+
this.op({ k: 'child' });
|
|
72
|
+
else if (parent.ns === 'svg' && !SVG_HTML_POINT.test(parent.name)) {
|
|
73
|
+
this.op({ k: 'child', in: parent.name, svg: true });
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
this.op({ k: 'child', in: parent.name });
|
|
61
77
|
if (next === undefined) {
|
|
62
78
|
this.parts.push([nodes.length === 1 ? CHILD_SOLE : CHILD_END, path]);
|
|
63
79
|
return;
|
|
@@ -69,17 +85,29 @@ class Emitter {
|
|
|
69
85
|
shape.push('#comment');
|
|
70
86
|
}
|
|
71
87
|
element(el, path) {
|
|
88
|
+
// `open` is the server's start tag; `client` leaves a static style to a part (below).
|
|
72
89
|
let open = `<${el.raw}`;
|
|
90
|
+
let client = open;
|
|
73
91
|
for (const a of el.attrs) {
|
|
74
|
-
if (a.kind
|
|
75
|
-
|
|
92
|
+
if (a.kind !== 'static')
|
|
93
|
+
continue;
|
|
94
|
+
const attr = a.value === null ? ` ${a.name}` : ` ${a.name}=${a.value}`;
|
|
95
|
+
open += attr;
|
|
96
|
+
if (a.css !== undefined && a.css !== '' && !this.staticStyles.includes(a.css)) {
|
|
97
|
+
this.staticStyles.push(a.css);
|
|
98
|
+
}
|
|
99
|
+
// The CSSOM applies it under a strict CSP, where Firefox blocks the attribute in a
|
|
100
|
+
// <template>'s HTML: a multi-attribute with no holes (attr-parts.ts writes it once).
|
|
101
|
+
if (a.css !== undefined && !this.server)
|
|
102
|
+
this.parts.push([MULTI_PART, path, 'style', [a.css]]);
|
|
103
|
+
else
|
|
104
|
+
client += attr;
|
|
76
105
|
}
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
this.html += client;
|
|
107
|
+
if (el.props !== undefined)
|
|
79
108
|
this.op({ k: 'open', tag: el.name, html: open, attrs: el.props });
|
|
80
|
-
}
|
|
81
109
|
else
|
|
82
|
-
this.
|
|
110
|
+
this.serverOut(open);
|
|
83
111
|
for (const a of el.attrs) {
|
|
84
112
|
if (a.kind === 'static')
|
|
85
113
|
continue;
|
|
@@ -114,7 +142,7 @@ class Emitter {
|
|
|
114
142
|
(first?.type === 'hole' || (first?.type === 'text' && first.raw.startsWith('\n')))) {
|
|
115
143
|
this.out('\n');
|
|
116
144
|
}
|
|
117
|
-
const shape = this.children(el.children, path, el
|
|
145
|
+
const shape = this.children(el.children, path, el);
|
|
118
146
|
if (el.props !== undefined) {
|
|
119
147
|
this.html += `</${el.raw}>`;
|
|
120
148
|
this.op({ k: 'close', tag: el.name });
|
|
@@ -131,6 +159,7 @@ class Emitter {
|
|
|
131
159
|
export function emit(root, server) {
|
|
132
160
|
const e = new Emitter(server);
|
|
133
161
|
const shape = e.children(root, []);
|
|
134
|
-
|
|
162
|
+
const { html, parts, segments, staticStyles } = e;
|
|
163
|
+
return { html, parts, segments, shape, staticStyles };
|
|
135
164
|
}
|
|
136
165
|
//# sourceMappingURL=emit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../../../src/view/normalize/emit.ts"],"names":[],"mappings":"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","sourcesContent":["// Emits the template object's markup from the normalizer's tree (view/01-templates.md steps 3\n// and 4): the client HTML (bound attributes removed, anchors added by view/02-bindings.md's\n// anchor rule), the server segments (types.ts), the part table with child-index paths, and the\n// shape of the DOM the browser must build (checked by prepare.ts).\nimport type { ElementNode, TreeNode } from './tree.js';\nimport {\n ATTR_PART,\n BOOL_PART,\n CHILD_BEFORE,\n CHILD_END,\n CHILD_SOLE,\n HOOK_PART,\n MULTI_PART,\n PROP_PART,\n TEXT_PART,\n type PartSpec,\n type Path,\n type Segment,\n type Shape,\n type ShapeNode,\n} from './types.js';\n\nconst ANCHOR = '<!---->';\n\nexport interface Emitted {\n readonly html: string;\n readonly parts: PartSpec[];\n readonly segments: Segment[];\n readonly shape: Shape;\n}\n\nclass Emitter {\n /** A page shell (`server`): never hydrated, so it needs no anchors (06). */\n constructor(private readonly server: boolean) {}\n\n html = '';\n readonly parts: PartSpec[] = [];\n readonly segments: Segment[] = [];\n\n /** Static markup: appended to the HTML and to the last string segment. */\n out(text: string): void {\n if (text === '') return;\n this.html += text;\n const last = this.segments.length - 1;\n const prev = this.segments[last];\n if (typeof prev === 'string') this.segments[last] = prev + text;\n else this.segments.push(text);\n }\n\n op(segment: Segment): void {\n this.segments.push(segment);\n }\n\n /** `parent`: the parent element's name; undefined at the template root. */\n children(nodes: readonly TreeNode[], path: Path, parent?: string): Shape {\n const shape: ShapeNode[] = [];\n nodes.forEach((node, k) => {\n switch (node.type) {\n case 'text':\n this.out(node.raw);\n shape.push('#text');\n return;\n case 'comment':\n this.out(node.raw);\n shape.push('#comment');\n return;\n case 'doctype':\n // Server templates only; the browser drops a doctype inside a fragment.\n this.out(node.raw);\n return;\n case 'el':\n shape.push(this.element(node, [...path, shape.length]));\n return;\n case 'hole':\n if (node.kind === 'text') {\n this.parts.push([TEXT_PART, path]);\n this.op({ k: 'text' });\n return;\n }\n this.child(nodes, k, path, shape, parent);\n }\n });\n return shape;\n }\n\n /** A child hole: inserts before the next static element or comment, the end, or an anchor. */\n private child(\n nodes: readonly TreeNode[],\n k: number,\n path: Path,\n shape: ShapeNode[],\n parent: string | undefined,\n ): void {\n const next = nodes[k + 1];\n this.op(parent === undefined ? { k: 'child' } : { k: 'child', in: parent });\n if (next === undefined) {\n this.parts.push([nodes.length === 1 ? CHILD_SOLE : CHILD_END, path]);\n return;\n }\n this.parts.push([CHILD_BEFORE, path, shape.length]);\n if (next.type === 'el' || next.type === 'comment' || this.server) return;\n this.out(ANCHOR);\n shape.push('#comment');\n }\n\n private element(el: ElementNode, path: Path): ShapeNode {\n let open = `<${el.raw}`;\n for (const a of el.attrs) {\n if (a.kind === 'static') open += a.value === null ? ` ${a.name}` : ` ${a.name}=${a.value}`;\n }\n if (el.props !== undefined) {\n this.html += open;\n this.op({ k: 'open', tag: el.name, html: open, attrs: el.props });\n } else this.out(open);\n for (const a of el.attrs) {\n if (a.kind === 'static') continue;\n if (a.kind === 'hook') {\n this.parts.push([HOOK_PART, path]);\n this.op({ k: 'hook' });\n } else if (a.kind === 'attr' && a.strings !== undefined) {\n this.parts.push([MULTI_PART, path, a.name, a.strings]);\n this.op({ k: 'attr', name: a.name, strings: a.strings });\n } else {\n const kind = a.kind === 'attr' ? ATTR_PART : a.kind === 'bool' ? BOOL_PART : PROP_PART;\n this.parts.push([kind, path, a.name]);\n this.op({ k: a.kind, name: a.name });\n }\n }\n const end = el.empty && el.ns !== 'html' ? '/>' : '>';\n if (el.props !== undefined) {\n this.html += end;\n this.op({ k: 'openEnd' });\n } else this.out(end);\n if (el.empty) return [el.name, []];\n // The parser drops a newline right after <pre>, <listing> and <textarea>: give it one to\n // drop, so a hole or text starting with a newline keeps its own.\n const first = el.children[0];\n const newline = el.ns === 'html' && /^(pre|listing|textarea)$/.test(el.name);\n if (\n newline &&\n (first?.type === 'hole' || (first?.type === 'text' && first.raw.startsWith('\\n')))\n ) {\n this.out('\\n');\n }\n const shape = this.children(el.children, path, el.name);\n if (el.props !== undefined) {\n this.html += `</${el.raw}>`;\n this.op({ k: 'close', tag: el.name });\n } else this.out(`</${el.raw}>`);\n return [el.name, shape];\n }\n}\n\n/**\n * Emits the HTML, part table, segments and shape for a template's tree. A `server` template\n * (a page shell) gets no anchors: hydration never walks it, and the browser never renders it.\n */\nexport function emit(root: readonly TreeNode[], server: boolean): Emitted {\n const e = new Emitter(server);\n const shape = e.children(root, []);\n return { html: e.html, parts: e.parts, segments: e.segments, shape };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"emit.js","sourceRoot":"","sources":["../../../src/view/normalize/emit.ts"],"names":[],"mappings":"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","sourcesContent":["// Emits the template object's markup from the normalizer's tree (view/01-templates.md steps 3\n// and 4): the client HTML (bound attributes and static `style` attributes removed, anchors\n// added by view/02-bindings.md's anchor rule), the server segments (types.ts), the part table\n// with child-index paths, and the shape of the DOM the browser must build (prepare.ts).\nimport { SVG_HTML_POINT } from './svg.js';\nimport type { ElementNode, TreeNode } from './tree.js';\nimport {\n ATTR_PART,\n BOOL_PART,\n CHILD_BEFORE,\n CHILD_END,\n CHILD_SOLE,\n HOOK_PART,\n MULTI_PART,\n PROP_PART,\n TEXT_PART,\n type PartSpec,\n type Path,\n type Segment,\n type Shape,\n type ShapeNode,\n} from './types.js';\n\nconst ANCHOR = '<!---->';\n\nexport interface Emitted {\n readonly html: string;\n readonly parts: PartSpec[];\n readonly segments: Segment[];\n readonly shape: Shape;\n /** The decoded values of the template's non-empty static `style` attributes (types.ts). */\n readonly staticStyles: string[];\n}\n\nclass Emitter {\n /** A page shell (`server`): never hydrated, so it needs no anchors (06). */\n constructor(private readonly server: boolean) {}\n\n html = '';\n readonly parts: PartSpec[] = [];\n readonly segments: Segment[] = [];\n readonly staticStyles: string[] = [];\n\n /** Static markup: appended to the HTML and to the last string segment. */\n out(text: string): void {\n this.html += text;\n this.serverOut(text);\n }\n\n /** Static markup only the server writes: appended to the last string segment. */\n serverOut(text: string): void {\n if (text === '') return;\n const last = this.segments.length - 1;\n const prev = this.segments[last];\n if (typeof prev === 'string') this.segments[last] = prev + text;\n else this.segments.push(text);\n }\n\n op(segment: Segment): void {\n this.segments.push(segment);\n }\n\n /** `parent`: the parent element; undefined at the template root. */\n children(nodes: readonly TreeNode[], path: Path, parent?: ElementNode): Shape {\n const shape: ShapeNode[] = [];\n nodes.forEach((node, k) => {\n switch (node.type) {\n case 'text':\n this.out(node.raw);\n shape.push('#text');\n return;\n case 'comment':\n this.out(node.raw);\n shape.push('#comment');\n return;\n case 'doctype':\n // Server templates only; the browser drops a doctype inside a fragment.\n this.out(node.raw);\n return;\n case 'el':\n shape.push(this.element(node, [...path, shape.length]));\n return;\n case 'hole':\n if (node.kind === 'text') {\n this.parts.push([TEXT_PART, path]);\n this.op({ k: 'text' });\n return;\n }\n this.child(nodes, k, path, shape, parent);\n }\n });\n return shape;\n }\n\n /** A child hole: inserts before the next static element or comment, the end, or an anchor. */\n private child(\n nodes: readonly TreeNode[],\n k: number,\n path: Path,\n shape: ShapeNode[],\n parent: ElementNode | undefined,\n ): void {\n const next = nodes[k + 1];\n if (parent === undefined) this.op({ k: 'child' });\n else if (parent.ns === 'svg' && !SVG_HTML_POINT.test(parent.name)) {\n this.op({ k: 'child', in: parent.name, svg: true });\n } else this.op({ k: 'child', in: parent.name });\n if (next === undefined) {\n this.parts.push([nodes.length === 1 ? CHILD_SOLE : CHILD_END, path]);\n return;\n }\n this.parts.push([CHILD_BEFORE, path, shape.length]);\n if (next.type === 'el' || next.type === 'comment' || this.server) return;\n this.out(ANCHOR);\n shape.push('#comment');\n }\n\n private element(el: ElementNode, path: Path): ShapeNode {\n // `open` is the server's start tag; `client` leaves a static style to a part (below).\n let open = `<${el.raw}`;\n let client = open;\n for (const a of el.attrs) {\n if (a.kind !== 'static') continue;\n const attr = a.value === null ? ` ${a.name}` : ` ${a.name}=${a.value}`;\n open += attr;\n if (a.css !== undefined && a.css !== '' && !this.staticStyles.includes(a.css)) {\n this.staticStyles.push(a.css);\n }\n // The CSSOM applies it under a strict CSP, where Firefox blocks the attribute in a\n // <template>'s HTML: a multi-attribute with no holes (attr-parts.ts writes it once).\n if (a.css !== undefined && !this.server)\n this.parts.push([MULTI_PART, path, 'style', [a.css]]);\n else client += attr;\n }\n this.html += client;\n if (el.props !== undefined) this.op({ k: 'open', tag: el.name, html: open, attrs: el.props });\n else this.serverOut(open);\n for (const a of el.attrs) {\n if (a.kind === 'static') continue;\n if (a.kind === 'hook') {\n this.parts.push([HOOK_PART, path]);\n this.op({ k: 'hook' });\n } else if (a.kind === 'attr' && a.strings !== undefined) {\n this.parts.push([MULTI_PART, path, a.name, a.strings]);\n this.op({ k: 'attr', name: a.name, strings: a.strings });\n } else {\n const kind = a.kind === 'attr' ? ATTR_PART : a.kind === 'bool' ? BOOL_PART : PROP_PART;\n this.parts.push([kind, path, a.name]);\n this.op({ k: a.kind, name: a.name });\n }\n }\n const end = el.empty && el.ns !== 'html' ? '/>' : '>';\n if (el.props !== undefined) {\n this.html += end;\n this.op({ k: 'openEnd' });\n } else this.out(end);\n if (el.empty) return [el.name, []];\n // The parser drops a newline right after <pre>, <listing> and <textarea>: give it one to\n // drop, so a hole or text starting with a newline keeps its own.\n const first = el.children[0];\n const newline = el.ns === 'html' && /^(pre|listing|textarea)$/.test(el.name);\n if (\n newline &&\n (first?.type === 'hole' || (first?.type === 'text' && first.raw.startsWith('\\n')))\n ) {\n this.out('\\n');\n }\n const shape = this.children(el.children, path, el);\n if (el.props !== undefined) {\n this.html += `</${el.raw}>`;\n this.op({ k: 'close', tag: el.name });\n } else this.out(`</${el.raw}>`);\n return [el.name, shape];\n }\n}\n\n/**\n * Emits the HTML, part table, segments and shape for a template's tree. A `server` template\n * (a page shell) gets no anchors: hydration never walks it, and the browser never renders it.\n */\nexport function emit(root: readonly TreeNode[], server: boolean): Emitted {\n const e = new Emitter(server);\n const shape = e.children(root, []);\n const { html, parts, segments, staticStyles } = e;\n return { html, parts, segments, shape, staticStyles };\n}\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
export const RULES_DOC = 'docs/design-docs/view/09-template-rules.md';
|
|
4
4
|
/** Rule 11's message, here so the client's template cache needn't load the rule messages. */
|
|
5
5
|
export const SERVER_ONLY = 'This template has document-level tags (<!doctype>, <html>, <head> or <body>): it is a page ' +
|
|
6
|
-
'shell, and only the server renders those. Render it with @gyral/
|
|
6
|
+
'shell, and only the server renders those. Render it with @gyral/ssr (renderPage, renderToString), and render ' +
|
|
7
7
|
'components (not the page) in the browser.';
|
|
8
8
|
/** A template breaks rule `rule` of view/09-template-rules.md. */
|
|
9
9
|
export class TemplateError extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/view/normalize/errors.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,mFAAmF;AAEnF,MAAM,CAAC,MAAM,SAAS,GAAG,4CAA4C,CAAC;AAEtE,6FAA6F;AAC7F,MAAM,CAAC,MAAM,WAAW,GACtB,6FAA6F;IAC7F
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/view/normalize/errors.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,mFAAmF;AAEnF,MAAM,CAAC,MAAM,SAAS,GAAG,4CAA4C,CAAC;AAEtE,6FAA6F;AAC7F,MAAM,CAAC,MAAM,WAAW,GACtB,6FAA6F;IAC7F,+GAA+G;IAC/G,2CAA2C,CAAC;AAE9C,kEAAkE;AAClE,MAAM,OAAO,aAAc,SAAQ,KAAK;IAItC,YAAY,IAAY,EAAE,OAAe,EAAE,GAAY,EAAE,IAAa;QACpE,MAAM,GAAG,GAAG,KAAK,SAAS,UAAU,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACpD,MAAM,OAAO,GACX,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QAC/F,KAAK,CAAC,wBAAwB,MAAM,CAAC,IAAI,CAAC,KAAK,OAAO,GAAG,GAAG,GAAG,OAAO,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;CACF","sourcesContent":["// TemplateError: what the template rules (view/09-template-rules.md) throw. Kept apart from the\n// rule checks so code that only needs the class (template-element.ts) stays small.\n\nexport const RULES_DOC = 'docs/design-docs/view/09-template-rules.md';\n\n/** Rule 11's message, here so the client's template cache needn't load the rule messages. */\nexport const SERVER_ONLY =\n 'This template has document-level tags (<!doctype>, <html>, <head> or <body>): it is a page ' +\n 'shell, and only the server renders those. Render it with @gyral/ssr (renderPage, renderToString), and render ' +\n 'components (not the page) in the browser.';\n\n/** A template breaks rule `rule` of view/09-template-rules.md. */\nexport class TemplateError extends Error {\n readonly rule: number;\n readonly loc: string | undefined;\n\n constructor(rule: number, message: string, loc?: string, near?: string) {\n const doc = ` (${RULES_DOC}, rule ${String(rule)})`;\n const context =\n (near === undefined ? '' : `\\n near: ${near}`) + (loc === undefined ? '' : `\\n at ${loc}`);\n super(`[gyral template rule ${String(rule)}] ${message}${doc}${context}`);\n this.name = 'TemplateError';\n this.rule = rule;\n this.loc = loc;\n }\n}\n"]}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The id of a template's normalized strings. `svg`: an svg template's (01 "svg templates"),
|
|
3
|
+
* whose DOM differs from an html template's with the same strings, so its id does too.
|
|
4
|
+
*/
|
|
5
|
+
export declare function templateId(strings: readonly string[], svg?: boolean): string;
|
|
3
6
|
/**
|
|
4
7
|
* Development: records `id` → strings and warns once when two different normalized templates
|
|
5
8
|
* share an id (the compiler fails the build instead).
|
|
@@ -11,10 +11,17 @@ function avalanche(h, a, b) {
|
|
|
11
11
|
x = Math.imul(x ^ (x >>> 13), b);
|
|
12
12
|
return x ^ (x >>> 16);
|
|
13
13
|
}
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The id of a template's normalized strings. `svg`: an svg template's (01 "svg templates"),
|
|
16
|
+
* whose DOM differs from an html template's with the same strings, so its id does too.
|
|
17
|
+
*/
|
|
18
|
+
export function templateId(strings, svg = false) {
|
|
16
19
|
let h1 = 0x9e3779b9 ^ strings.length;
|
|
17
20
|
let h2 = 0x85ebca6b ^ strings.length;
|
|
21
|
+
if (svg) {
|
|
22
|
+
h1 = mix(h1, 0x737667, 0x2d51);
|
|
23
|
+
h2 = mix(h2, 0x737667, 0x1b873593);
|
|
24
|
+
}
|
|
18
25
|
for (const s of strings) {
|
|
19
26
|
h1 = mix(h1, s.length, 0x2d51);
|
|
20
27
|
h2 = mix(h2, s.length, 0x1b873593);
|