@microsoft/fast-element 2.10.3 → 3.0.0-rc.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/ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md +1 -1
- package/ARCHITECTURE_OVERVIEW.md +2 -2
- package/CHANGELOG.json +31 -1
- package/CHANGELOG.md +10 -2
- package/DECLARATIVE_DESIGN.md +806 -0
- package/DECLARATIVE_HTML.md +470 -0
- package/DECLARATIVE_MIGRATION.md +215 -0
- package/DECLARATIVE_RENDERING.md +530 -0
- package/DECLARATIVE_RENDERING_LIFECYCLE.md +288 -0
- package/DECLARATIVE_SCHEMA_OBSERVER_MAP.md +489 -0
- package/DESIGN.md +143 -34
- package/MIGRATION.md +387 -0
- package/README.md +208 -1
- package/SIZES.md +25 -0
- package/api-extractor.arrays.json +15 -0
- package/api-extractor.context.json +1 -0
- package/api-extractor.declarative.json +15 -0
- package/api-extractor.di.json +1 -0
- package/api-extractor.hydration.json +15 -0
- package/api-extractor.styles.json +15 -0
- package/dist/arrays/arrays.api.json +2621 -0
- package/dist/context/context.api.json +1 -1
- package/dist/declarative/declarative.api.json +7844 -0
- package/dist/di/di.api.json +2 -2
- package/dist/dts/array-observer.d.ts +2 -0
- package/dist/dts/arrays.d.ts +2 -0
- package/dist/dts/attr.d.ts +1 -0
- package/dist/dts/binding/signal.d.ts +6 -6
- package/dist/dts/binding/two-way.d.ts +1 -0
- package/dist/dts/binding.d.ts +7 -0
- package/dist/dts/components/attributes.d.ts +2 -5
- package/dist/dts/components/definition-schema-transforms.d.ts +9 -0
- package/dist/dts/components/element-controller.d.ts +80 -114
- package/dist/dts/components/element-hydration.d.ts +1 -1
- package/dist/dts/components/enable-hydration.d.ts +34 -0
- package/dist/dts/components/fast-definitions.d.ts +91 -42
- package/dist/dts/components/fast-element.d.ts +5 -8
- package/dist/dts/components/hydration-tracker.d.ts +40 -0
- package/dist/dts/components/hydration.d.ts +18 -53
- package/dist/dts/components/schema.d.ts +205 -0
- package/dist/dts/context.d.ts +6 -6
- package/dist/dts/css.d.ts +3 -0
- package/dist/dts/debug.d.ts +5 -1
- package/dist/dts/declarative/attribute-map.d.ts +58 -0
- package/dist/dts/declarative/debug.d.ts +5 -0
- package/dist/dts/declarative/index.d.ts +13 -0
- package/dist/dts/declarative/interfaces.d.ts +9 -0
- package/dist/dts/declarative/observer-map-utilities.d.ts +58 -0
- package/dist/dts/declarative/observer-map.d.ts +89 -0
- package/dist/dts/declarative/runtime.d.ts +5 -0
- package/dist/dts/declarative/syntax.d.ts +21 -0
- package/dist/dts/declarative/template-bridge.d.ts +33 -0
- package/dist/dts/declarative/template-parser.d.ts +98 -0
- package/dist/dts/declarative/template.d.ts +9 -0
- package/dist/dts/declarative/utilities.d.ts +312 -0
- package/dist/dts/di/di.d.ts +1 -1
- package/dist/dts/directives/children.d.ts +2 -0
- package/dist/dts/directives/node-observation.d.ts +2 -0
- package/dist/dts/directives/ref.d.ts +2 -0
- package/dist/dts/directives/repeat.d.ts +4 -0
- package/dist/dts/directives/slotted.d.ts +2 -0
- package/dist/dts/directives/when.d.ts +3 -0
- package/dist/dts/dom-policy.d.ts +1 -1
- package/dist/dts/html.d.ts +5 -0
- package/dist/dts/hydration/runtime.d.ts +7 -0
- package/dist/dts/hydration/target-builder.d.ts +15 -12
- package/dist/dts/hydration.d.ts +14 -0
- package/dist/dts/index.d.ts +38 -42
- package/dist/dts/index.debug.d.ts +0 -1
- package/dist/dts/index.rollup.debug.d.ts +0 -1
- package/dist/dts/interfaces.d.ts +1 -49
- package/dist/dts/observable.d.ts +3 -6
- package/dist/dts/observation/arrays.d.ts +1 -1
- package/dist/dts/observation/update-queue.d.ts +1 -1
- package/dist/dts/platform.d.ts +25 -4
- package/dist/dts/render.d.ts +7 -0
- package/dist/dts/schema.d.ts +1 -0
- package/dist/dts/state/exports.d.ts +1 -1
- package/dist/dts/state/state.d.ts +2 -2
- package/dist/dts/styles/css-directive.d.ts +5 -12
- package/dist/dts/styles/css.d.ts +5 -7
- package/dist/dts/styles/element-styles.d.ts +0 -10
- package/dist/dts/styles.d.ts +6 -0
- package/dist/dts/templating/children.d.ts +1 -1
- package/dist/dts/templating/html-binding-directive.d.ts +10 -0
- package/dist/dts/templating/html-directive.d.ts +17 -0
- package/dist/dts/templating/hydration-view.d.ts +109 -0
- package/dist/dts/templating/ref.d.ts +1 -1
- package/dist/dts/templating/render.d.ts +8 -2
- package/dist/dts/templating/repeat.d.ts +2 -2
- package/dist/dts/templating/slotted.d.ts +1 -1
- package/dist/dts/templating/template.d.ts +17 -9
- package/dist/dts/templating/view.d.ts +25 -102
- package/dist/dts/templating/when.d.ts +1 -1
- package/dist/dts/templating.d.ts +10 -0
- package/dist/dts/testing/exports.d.ts +2 -2
- package/dist/dts/tsdoc-metadata.json +1 -1
- package/dist/dts/updates.d.ts +1 -0
- package/dist/dts/volatile.d.ts +2 -0
- package/dist/esm/array-observer.js +1 -0
- package/dist/esm/arrays.js +1 -0
- package/dist/esm/attr.js +1 -0
- package/dist/esm/binding/normalize.js +1 -1
- package/dist/esm/binding/signal.js +4 -4
- package/dist/esm/binding/two-way.js +2 -1
- package/dist/esm/binding.js +4 -0
- package/dist/esm/components/attributes.js +8 -5
- package/dist/esm/components/definition-schema-transforms.js +23 -0
- package/dist/esm/components/element-controller.js +200 -269
- package/dist/esm/components/element-hydration.js +1 -1
- package/dist/esm/components/enable-hydration.js +100 -0
- package/dist/esm/components/fast-definitions.js +211 -49
- package/dist/esm/components/fast-element.js +18 -27
- package/dist/esm/components/hydration-tracker.js +93 -0
- package/dist/esm/components/hydration.js +62 -144
- package/dist/esm/components/schema.js +253 -0
- package/dist/esm/context.js +6 -6
- package/dist/esm/css.js +3 -0
- package/dist/esm/debug.js +26 -26
- package/dist/esm/declarative/attribute-map.js +121 -0
- package/dist/esm/declarative/debug.js +5 -0
- package/dist/esm/declarative/index.js +3 -0
- package/dist/esm/declarative/interfaces.js +10 -0
- package/dist/esm/declarative/observer-map-utilities.js +562 -0
- package/dist/esm/declarative/observer-map.js +216 -0
- package/dist/esm/declarative/runtime.js +14 -0
- package/dist/esm/declarative/syntax.js +36 -0
- package/dist/esm/declarative/template-bridge.js +170 -0
- package/dist/esm/declarative/template-parser.js +306 -0
- package/dist/esm/declarative/template.js +142 -0
- package/dist/esm/declarative/utilities.js +834 -0
- package/dist/esm/di/di.js +6 -8
- package/dist/esm/directives/children.js +1 -0
- package/dist/esm/directives/node-observation.js +1 -0
- package/dist/esm/directives/ref.js +1 -0
- package/dist/esm/directives/repeat.js +1 -0
- package/dist/esm/directives/slotted.js +1 -0
- package/dist/esm/directives/when.js +1 -0
- package/dist/esm/dom-policy.js +2 -2
- package/dist/esm/dom.js +1 -1
- package/dist/esm/html.js +2 -0
- package/dist/esm/hydration/runtime.js +33 -0
- package/dist/esm/hydration/target-builder.js +97 -90
- package/dist/esm/hydration.js +4 -0
- package/dist/esm/index.debug.js +2 -1
- package/dist/esm/index.js +34 -29
- package/dist/esm/index.rollup.debug.js +3 -2
- package/dist/esm/index.rollup.js +1 -1
- package/dist/esm/interfaces.js +1 -45
- package/dist/esm/observable.js +1 -4
- package/dist/esm/observation/arrays.js +1 -1
- package/dist/esm/observation/observable.js +5 -5
- package/dist/esm/observation/update-queue.js +47 -58
- package/dist/esm/platform.js +31 -30
- package/dist/esm/render.js +1 -0
- package/dist/esm/schema.js +1 -0
- package/dist/esm/state/exports.js +1 -1
- package/dist/esm/styles/css-directive.js +1 -2
- package/dist/esm/styles/css.js +15 -56
- package/dist/esm/styles/element-styles.js +69 -15
- package/dist/esm/styles.js +2 -0
- package/dist/esm/templating/html-binding-directive.js +24 -10
- package/dist/esm/templating/hydration-view.js +235 -0
- package/dist/esm/templating/render.js +13 -2
- package/dist/esm/templating/repeat.js +36 -34
- package/dist/esm/templating/template.js +7 -7
- package/dist/esm/templating/view.js +24 -233
- package/dist/esm/templating.js +7 -0
- package/dist/esm/testing/exports.js +2 -2
- package/dist/esm/updates.js +1 -0
- package/dist/esm/volatile.js +1 -0
- package/dist/fast-element.api.json +9017 -6996
- package/dist/fast-element.d.ts +3557 -796
- package/dist/fast-element.debug.js +5093 -4419
- package/dist/fast-element.debug.min.js +2 -2
- package/dist/fast-element.js +5398 -4655
- package/dist/fast-element.min.js +2 -2
- package/dist/fast-element.untrimmed.d.ts +881 -481
- package/dist/hydration/hydration.api.json +5237 -0
- package/dist/styles/styles.api.json +2672 -0
- package/docs/api-report.api.md +344 -167
- package/docs/arrays/api-report.api.md +114 -0
- package/docs/declarative/api-report.api.md +397 -0
- package/docs/hydration/api-report.api.md +285 -0
- package/docs/styles/api-report.api.md +135 -0
- package/package.json +149 -40
- package/playwright.declarative.config.ts +26 -0
- package/playwright.declarative.webui.config.ts +20 -0
- package/scripts/declarative/build-fixtures-with-webui.js +135 -0
- package/scripts/declarative/build-fixtures.js +49 -0
- package/scripts/declarative/build-fixtures.utilities.js +101 -0
- package/scripts/measure-sizes.js +219 -0
- package/scripts/run-api-extractor.js +39 -20
- package/test/declarative/fixtures/README.md +72 -0
- package/test/declarative/fixtures/WRITING_FIXTURES.md +330 -0
- package/test/declarative/fixtures/bindings/README.md +12 -0
- package/test/declarative/fixtures/bindings/attribute/entry.html +13 -0
- package/test/declarative/fixtures/bindings/attribute/fast-build.config.json +6 -0
- package/test/declarative/fixtures/bindings/attribute/index.html +25 -0
- package/test/declarative/fixtures/bindings/attribute/main.ts +41 -0
- package/test/declarative/fixtures/bindings/attribute/state.json +8 -0
- package/test/declarative/fixtures/bindings/attribute/templates.html +11 -0
- package/test/declarative/fixtures/bindings/content/entry.html +12 -0
- package/test/declarative/fixtures/bindings/content/fast-build.config.json +6 -0
- package/test/declarative/fixtures/bindings/content/index.html +19 -0
- package/test/declarative/fixtures/bindings/content/main.ts +27 -0
- package/test/declarative/fixtures/bindings/content/state.json +4 -0
- package/test/declarative/fixtures/bindings/content/templates.html +6 -0
- package/test/declarative/fixtures/bindings/dot-syntax/entry.html +11 -0
- package/test/declarative/fixtures/bindings/dot-syntax/fast-build.config.json +6 -0
- package/test/declarative/fixtures/bindings/dot-syntax/index.html +47 -0
- package/test/declarative/fixtures/bindings/dot-syntax/main.ts +59 -0
- package/test/declarative/fixtures/bindings/dot-syntax/state.json +16 -0
- package/test/declarative/fixtures/bindings/dot-syntax/templates.html +17 -0
- package/test/declarative/fixtures/bindings/event/entry.html +11 -0
- package/test/declarative/fixtures/bindings/event/fast-build.config.json +6 -0
- package/test/declarative/fixtures/bindings/event/index.html +43 -0
- package/test/declarative/fixtures/bindings/event/main.ts +43 -0
- package/test/declarative/fixtures/bindings/event/state.json +3 -0
- package/test/declarative/fixtures/bindings/event/templates.html +18 -0
- package/test/declarative/fixtures/bindings/host/entry.html +40 -0
- package/test/declarative/fixtures/bindings/host/fast-build.config.json +6 -0
- package/test/declarative/fixtures/bindings/host/index.html +96 -0
- package/test/declarative/fixtures/bindings/host/main.ts +222 -0
- package/test/declarative/fixtures/bindings/host/state.json +9 -0
- package/test/declarative/fixtures/bindings/host/templates.html +55 -0
- package/test/declarative/fixtures/directives/README.md +12 -0
- package/test/declarative/fixtures/directives/children/entry.html +11 -0
- package/test/declarative/fixtures/directives/children/fast-build.config.json +6 -0
- package/test/declarative/fixtures/directives/children/index.html +15 -0
- package/test/declarative/fixtures/directives/children/main.ts +22 -0
- package/test/declarative/fixtures/directives/children/state.json +3 -0
- package/test/declarative/fixtures/directives/children/templates.html +3 -0
- package/test/declarative/fixtures/directives/ref/entry.html +11 -0
- package/test/declarative/fixtures/directives/ref/fast-build.config.json +6 -0
- package/test/declarative/fixtures/directives/ref/index.html +15 -0
- package/test/declarative/fixtures/directives/ref/main.ts +17 -0
- package/test/declarative/fixtures/directives/ref/state.json +1 -0
- package/test/declarative/fixtures/directives/ref/templates.html +3 -0
- package/test/declarative/fixtures/directives/repeat/entry.html +21 -0
- package/test/declarative/fixtures/directives/repeat/fast-build.config.json +6 -0
- package/test/declarative/fixtures/directives/repeat/index.html +133 -0
- package/test/declarative/fixtures/directives/repeat/main.ts +110 -0
- package/test/declarative/fixtures/directives/repeat/sprites.svg +8 -0
- package/test/declarative/fixtures/directives/repeat/state.json +10 -0
- package/test/declarative/fixtures/directives/repeat/templates.html +75 -0
- package/test/declarative/fixtures/directives/slotted/entry.html +17 -0
- package/test/declarative/fixtures/directives/slotted/fast-build.config.json +6 -0
- package/test/declarative/fixtures/directives/slotted/index.html +27 -0
- package/test/declarative/fixtures/directives/slotted/main.ts +29 -0
- package/test/declarative/fixtures/directives/slotted/state.json +1 -0
- package/test/declarative/fixtures/directives/slotted/templates.html +7 -0
- package/test/declarative/fixtures/directives/when/entry.html +51 -0
- package/test/declarative/fixtures/directives/when/fast-build.config.json +6 -0
- package/test/declarative/fixtures/directives/when/index.html +136 -0
- package/test/declarative/fixtures/directives/when/main.ts +172 -0
- package/test/declarative/fixtures/directives/when/state.json +12 -0
- package/test/declarative/fixtures/directives/when/templates.html +75 -0
- package/test/declarative/fixtures/ecosystem/README.md +11 -0
- package/test/declarative/fixtures/ecosystem/declarative-no-hydration/entry.html +12 -0
- package/test/declarative/fixtures/ecosystem/declarative-no-hydration/fast-build.config.json +6 -0
- package/test/declarative/fixtures/ecosystem/declarative-no-hydration/index.html +20 -0
- package/test/declarative/fixtures/ecosystem/declarative-no-hydration/main.ts +68 -0
- package/test/declarative/fixtures/ecosystem/declarative-no-hydration/state.json +4 -0
- package/test/declarative/fixtures/ecosystem/declarative-no-hydration/templates.html +7 -0
- package/test/declarative/fixtures/ecosystem/errors/entry.html +12 -0
- package/test/declarative/fixtures/ecosystem/errors/fast-build.config.json +6 -0
- package/test/declarative/fixtures/ecosystem/errors/index.html +20 -0
- package/test/declarative/fixtures/ecosystem/errors/main.ts +17 -0
- package/test/declarative/fixtures/ecosystem/errors/state.json +1 -0
- package/test/declarative/fixtures/ecosystem/errors/templates.html +7 -0
- package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/entry.html +17 -0
- package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/fast-build.config.json +6 -0
- package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/index.html +56 -0
- package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/main.ts +134 -0
- package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/state.json +12 -0
- package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/templates.html +34 -0
- package/test/declarative/fixtures/ecosystem/performance-metrics/entry.html +25 -0
- package/test/declarative/fixtures/ecosystem/performance-metrics/fast-build.config.json +6 -0
- package/test/declarative/fixtures/ecosystem/performance-metrics/fast-card.css +10 -0
- package/test/declarative/fixtures/ecosystem/performance-metrics/index.html +181 -0
- package/test/declarative/fixtures/ecosystem/performance-metrics/main.ts +58 -0
- package/test/declarative/fixtures/ecosystem/performance-metrics/state.json +6 -0
- package/test/declarative/fixtures/ecosystem/performance-metrics/templates.html +15 -0
- package/test/declarative/fixtures/extensions/README.md +15 -0
- package/test/declarative/fixtures/extensions/attribute-map/entry.html +14 -0
- package/test/declarative/fixtures/extensions/attribute-map/fast-build.config.json +6 -0
- package/test/declarative/fixtures/extensions/attribute-map/index.html +31 -0
- package/test/declarative/fixtures/extensions/attribute-map/main.ts +40 -0
- package/test/declarative/fixtures/extensions/attribute-map/state.json +4 -0
- package/test/declarative/fixtures/extensions/attribute-map/templates.html +14 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/entry.html +12 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/fast-build.config.json +7 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/index.html +25 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/main.ts +31 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/state.json +5 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/templates.html +11 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/entry.html +13 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/fast-build.config.json +7 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/index.html +23 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/main.ts +37 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/state.json +1 -0
- package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/templates.html +9 -0
- package/test/declarative/fixtures/extensions/observer-map/entry.html +15 -0
- package/test/declarative/fixtures/extensions/observer-map/fast-build.config.json +6 -0
- package/test/declarative/fixtures/extensions/observer-map/index.html +442 -0
- package/test/declarative/fixtures/extensions/observer-map/main.ts +482 -0
- package/test/declarative/fixtures/extensions/observer-map/state.json +158 -0
- package/test/declarative/fixtures/extensions/observer-map/templates.html +172 -0
- package/test/declarative/fixtures/extensions/observer-map-config-object/entry.html +16 -0
- package/test/declarative/fixtures/extensions/observer-map-config-object/fast-build.config.json +6 -0
- package/test/declarative/fixtures/extensions/observer-map-config-object/index.html +27 -0
- package/test/declarative/fixtures/extensions/observer-map-config-object/main.ts +53 -0
- package/test/declarative/fixtures/extensions/observer-map-config-object/state.json +9 -0
- package/test/declarative/fixtures/extensions/observer-map-config-object/templates.html +12 -0
- package/test/declarative/fixtures/extensions/observer-map-deep-merge/README.md +98 -0
- package/test/declarative/fixtures/extensions/observer-map-deep-merge/entry.html +156 -0
- package/test/declarative/fixtures/extensions/observer-map-deep-merge/fast-build.config.json +6 -0
- package/test/declarative/fixtures/extensions/observer-map-deep-merge/index.html +376 -0
- package/test/declarative/fixtures/extensions/observer-map-deep-merge/main.ts +366 -0
- package/test/declarative/fixtures/extensions/observer-map-deep-merge/state.json +69 -0
- package/test/declarative/fixtures/extensions/observer-map-deep-merge/templates.html +91 -0
- package/test/declarative/fixtures/extensions/observer-map-properties/entry.html +14 -0
- package/test/declarative/fixtures/extensions/observer-map-properties/fast-build.config.json +6 -0
- package/test/declarative/fixtures/extensions/observer-map-properties/index.html +110 -0
- package/test/declarative/fixtures/extensions/observer-map-properties/main.ts +175 -0
- package/test/declarative/fixtures/extensions/observer-map-properties/state.json +29 -0
- package/test/declarative/fixtures/extensions/observer-map-properties/templates.html +55 -0
- package/test/declarative/fixtures/scenarios/README.md +7 -0
- package/test/declarative/fixtures/scenarios/nested-elements/entry.html +16 -0
- package/test/declarative/fixtures/scenarios/nested-elements/fast-build.config.json +6 -0
- package/test/declarative/fixtures/scenarios/nested-elements/index.html +126 -0
- package/test/declarative/fixtures/scenarios/nested-elements/main.ts +214 -0
- package/test/declarative/fixtures/scenarios/nested-elements/state.json +10 -0
- package/test/declarative/fixtures/scenarios/nested-elements/templates.html +54 -0
- package/test/declarative/index.html +12 -0
- package/test/declarative/vite.config.ts +55 -0
- package/test/declarative-main.ts +6 -0
- package/test/extension-subpaths-main.ts +9 -0
- package/test/main.ts +38 -33
- package/test/pure-declarative-main.ts +1 -0
- package/dist/dts/components/install-hydration.d.ts +0 -1
- package/dist/dts/pending-task.d.ts +0 -32
- package/dist/dts/polyfills.d.ts +0 -0
- package/dist/dts/styles/css-binding-directive.d.ts +0 -60
- package/dist/dts/templating/install-hydratable-view-templates.d.ts +0 -1
- package/dist/esm/components/install-hydration.js +0 -3
- package/dist/esm/pending-task.js +0 -28
- package/dist/esm/polyfills.js +0 -60
- package/dist/esm/styles/css-binding-directive.js +0 -76
- package/dist/esm/templating/install-hydratable-view-templates.js +0 -23
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
process.env.FAST_WEBUI_INTEGRATION = "true";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
testDir: "./test/declarative/fixtures",
|
|
7
|
+
testMatch: "**/*.spec.ts",
|
|
8
|
+
retries: 3,
|
|
9
|
+
projects: [
|
|
10
|
+
{
|
|
11
|
+
name: "chromium",
|
|
12
|
+
use: { ...devices["Desktop Chrome"] },
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
webServer: {
|
|
16
|
+
command: "npm run test-server:declarative:webui",
|
|
17
|
+
port: 5174,
|
|
18
|
+
reuseExistingServer: true,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build FAST HTML fixtures with @microsoft/webui.
|
|
5
|
+
*
|
|
6
|
+
* For each fixture directory this script:
|
|
7
|
+
* 1. Extracts <f-template> components from templates.html into individual
|
|
8
|
+
* component files (webui uses filename-based component discovery).
|
|
9
|
+
* 2. Builds the fixture with `webui build --plugin=fast`.
|
|
10
|
+
* 3. Renders the compiled protocol with the fixture's state.json.
|
|
11
|
+
* 4. Writes the rendered index.html into temp/integrations/webui/fixtures/
|
|
12
|
+
* alongside a copy of main.ts and any extra assets so that Playwright
|
|
13
|
+
* tests can run against the webui-rendered output via Vite.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
copyFileSync,
|
|
18
|
+
existsSync,
|
|
19
|
+
mkdirSync,
|
|
20
|
+
readdirSync,
|
|
21
|
+
readFileSync,
|
|
22
|
+
rmSync,
|
|
23
|
+
writeFileSync,
|
|
24
|
+
} from "node:fs";
|
|
25
|
+
import { dirname, join, resolve } from "node:path";
|
|
26
|
+
import { fileURLToPath } from "node:url";
|
|
27
|
+
import { build, render } from "@microsoft/webui";
|
|
28
|
+
import {
|
|
29
|
+
convertToWebuiSyntax,
|
|
30
|
+
discoverFixtures,
|
|
31
|
+
extractFTemplates,
|
|
32
|
+
} from "./build-fixtures.utilities.js";
|
|
33
|
+
|
|
34
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
35
|
+
const fixturesDir = resolve(__dirname, "../../test/declarative/fixtures");
|
|
36
|
+
const fixtures = discoverFixtures(fixturesDir);
|
|
37
|
+
const outBase = resolve(__dirname, "../../temp/integrations/webui/fixtures");
|
|
38
|
+
|
|
39
|
+
// Files produced by the build or only needed for the build step.
|
|
40
|
+
const buildOnlyFiles = new Set([
|
|
41
|
+
"entry.html",
|
|
42
|
+
"fast-build.config.json",
|
|
43
|
+
"templates.html",
|
|
44
|
+
"state.json",
|
|
45
|
+
"index.html",
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build a single fixture with webui and write the rendered output plus
|
|
50
|
+
* supporting files into the output directory.
|
|
51
|
+
*/
|
|
52
|
+
function buildFixture(fixtureName) {
|
|
53
|
+
const fixtureDir = join(fixturesDir, fixtureName);
|
|
54
|
+
const buildDir = join(outBase, ".build", fixtureName);
|
|
55
|
+
const buildOutDir = join(buildDir, "out");
|
|
56
|
+
const fixtureOutDir = join(outBase, fixtureName);
|
|
57
|
+
|
|
58
|
+
mkdirSync(buildDir, { recursive: true });
|
|
59
|
+
mkdirSync(buildOutDir, { recursive: true });
|
|
60
|
+
mkdirSync(fixtureOutDir, { recursive: true });
|
|
61
|
+
|
|
62
|
+
// Extract individual component HTML files for webui discovery,
|
|
63
|
+
// converting FAST directives to webui syntax.
|
|
64
|
+
const templatesHtml = readFileSync(join(fixtureDir, "templates.html"), "utf8");
|
|
65
|
+
const templates = extractFTemplates(templatesHtml);
|
|
66
|
+
|
|
67
|
+
for (const { name, content } of templates) {
|
|
68
|
+
writeFileSync(join(buildDir, `${name}.html`), convertToWebuiSyntax(content));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Prepare entry.html without script tags for webui build
|
|
72
|
+
const entryHtml = readFileSync(join(fixtureDir, "entry.html"), "utf8");
|
|
73
|
+
const cleanedEntry = entryHtml
|
|
74
|
+
.split("\n")
|
|
75
|
+
.filter(line => !line.includes("<script"))
|
|
76
|
+
.join("\n");
|
|
77
|
+
writeFileSync(join(buildDir, "entry.html"), cleanedEntry);
|
|
78
|
+
|
|
79
|
+
// Build protocol
|
|
80
|
+
const buildResult = build({
|
|
81
|
+
appDir: buildDir,
|
|
82
|
+
entry: "entry.html",
|
|
83
|
+
plugin: "fast",
|
|
84
|
+
outDir: buildOutDir,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!buildResult.protocol || buildResult.protocol.length === 0) {
|
|
88
|
+
throw new Error(`Build produced empty protocol for "${fixtureName}"`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Render with state
|
|
92
|
+
const state = JSON.parse(readFileSync(join(fixtureDir, "state.json"), "utf8"));
|
|
93
|
+
let html = render(buildResult.protocol, state, {
|
|
94
|
+
plugin: "fast",
|
|
95
|
+
entry: "entry.html",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Inject <script type="module" src="./main.ts"> before </body>
|
|
99
|
+
html = html.replace(
|
|
100
|
+
"</body>",
|
|
101
|
+
'<script type="module" src="./main.ts"></script>\n</body>',
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
writeFileSync(join(fixtureOutDir, "index.html"), html);
|
|
105
|
+
|
|
106
|
+
// Copy main.ts and any extra assets (CSS, SVG, etc.) from the
|
|
107
|
+
// original fixture directory so Vite can serve them.
|
|
108
|
+
for (const entry of readdirSync(fixtureDir)) {
|
|
109
|
+
if (buildOnlyFiles.has(entry) || entry.endsWith(".spec.ts")) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
copyFileSync(join(fixtureDir, entry), join(fixtureOutDir, entry));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
process.stdout.write(`Fixture "${fixtureName}" built successfully.\n`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function main() {
|
|
119
|
+
// Clean previous build output
|
|
120
|
+
if (existsSync(outBase)) {
|
|
121
|
+
rmSync(outBase, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
for (const fixtureName of fixtures) {
|
|
125
|
+
buildFixture(fixtureName);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Clean up intermediate build directory
|
|
129
|
+
const buildTmp = join(outBase, ".build");
|
|
130
|
+
if (existsSync(buildTmp)) {
|
|
131
|
+
rmSync(buildTmp, { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
main();
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { discoverFixtures } from "./build-fixtures.utilities.js";
|
|
8
|
+
|
|
9
|
+
// Pass-through CLI arguments (forwarded to every fast-build invocation).
|
|
10
|
+
const passthroughArgs = process.argv.slice(2);
|
|
11
|
+
|
|
12
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const fixturesDir = resolve(__dirname, "../../test/declarative/fixtures");
|
|
14
|
+
const fixtures = discoverFixtures(fixturesDir);
|
|
15
|
+
|
|
16
|
+
const require = createRequire(import.meta.url);
|
|
17
|
+
const fastBin = require.resolve("@microsoft/fast-build/bin/fast.js");
|
|
18
|
+
|
|
19
|
+
for (const fixtureName of fixtures) {
|
|
20
|
+
const fixtureDir = resolve(__dirname, "../../test/declarative/fixtures", fixtureName);
|
|
21
|
+
const configFile = join(fixtureDir, "fast-build.config.json");
|
|
22
|
+
const templatesFile = join(fixtureDir, "templates.html");
|
|
23
|
+
const outputFile = join(fixtureDir, "index.html");
|
|
24
|
+
|
|
25
|
+
// Step 1: render shadow DOM via fast-build CLI using config file
|
|
26
|
+
execFileSync(
|
|
27
|
+
process.execPath,
|
|
28
|
+
[fastBin, "build", `--config=${configFile}`, ...passthroughArgs],
|
|
29
|
+
{ stdio: "inherit" },
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Step 2: inject <f-template> declarations from templates.html before <script>
|
|
33
|
+
const fTemplates = readFileSync(templatesFile, "utf8").trim();
|
|
34
|
+
const rawHtml = readFileSync(outputFile, "utf8");
|
|
35
|
+
|
|
36
|
+
if (!rawHtml.includes('<script type="module"')) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Fixture "${fixtureName}": could not find '<script type="module"' in "${outputFile}". Template injection failed.`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const html = rawHtml.replace(
|
|
43
|
+
/(\s*)<script type="module"/,
|
|
44
|
+
`\n${fTemplates}\n$1<script type="module"`,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
writeFileSync(outputFile, html);
|
|
48
|
+
process.stdout.write(`Fixture "${fixtureName}" built successfully.\n`);
|
|
49
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Auto-discover fixture directories that contain the required build files
|
|
6
|
+
* (entry.html, templates.html, state.json, and fast-build.config.json).
|
|
7
|
+
*
|
|
8
|
+
* Fixtures are organized in category subdirectories (e.g., bindings/attribute,
|
|
9
|
+
* directives/repeat). The function scans two levels deep: category directories
|
|
10
|
+
* at the top level, and fixture directories within each category.
|
|
11
|
+
*
|
|
12
|
+
* Each fixture directory must contain a `fast-build.config.json` that
|
|
13
|
+
* configures the `@microsoft/fast-build` CLI. At minimum the config
|
|
14
|
+
* should specify `entry`, `state`, `output`, and `templates`. Fixture-
|
|
15
|
+
* specific options such as `attribute-name-strategy` can also be included.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} fixturesDir - Absolute path to the fixtures directory.
|
|
18
|
+
* @returns {string[]} Sorted array of fixture paths relative to fixturesDir
|
|
19
|
+
* (e.g., "bindings/attribute", "directives/repeat").
|
|
20
|
+
*/
|
|
21
|
+
export function discoverFixtures(fixturesDir) {
|
|
22
|
+
const fixtures = [];
|
|
23
|
+
|
|
24
|
+
for (const category of readdirSync(fixturesDir, { withFileTypes: true })) {
|
|
25
|
+
if (!category.isDirectory()) continue;
|
|
26
|
+
|
|
27
|
+
const categoryDir = join(fixturesDir, category.name);
|
|
28
|
+
|
|
29
|
+
for (const fixture of readdirSync(categoryDir, { withFileTypes: true })) {
|
|
30
|
+
if (!fixture.isDirectory()) continue;
|
|
31
|
+
|
|
32
|
+
const dir = join(categoryDir, fixture.name);
|
|
33
|
+
if (
|
|
34
|
+
existsSync(join(dir, "entry.html")) &&
|
|
35
|
+
existsSync(join(dir, "templates.html")) &&
|
|
36
|
+
existsSync(join(dir, "state.json")) &&
|
|
37
|
+
existsSync(join(dir, "fast-build.config.json"))
|
|
38
|
+
) {
|
|
39
|
+
fixtures.push(`${category.name}/${fixture.name}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return fixtures.sort((a, b) => a.localeCompare(b));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Extract `<f-template name="X">` elements from an HTML string.
|
|
49
|
+
* Returns an array of `{ name, content }` objects where `content`
|
|
50
|
+
* is the inner HTML of the `<template>` child. When the `<template>`
|
|
51
|
+
* element carries host-binding attributes (e.g. `@click`, `?disabled`),
|
|
52
|
+
* those are preserved by wrapping the content in a `<template>` tag.
|
|
53
|
+
* @param {string} html - Raw HTML containing `<f-template>` elements.
|
|
54
|
+
* @returns {{ name: string, content: string }[]}
|
|
55
|
+
*/
|
|
56
|
+
export function extractFTemplates(html) {
|
|
57
|
+
const results = [];
|
|
58
|
+
const regex =
|
|
59
|
+
/<f-template\s+name="([^"]+)">\s*<template([^>]*)>([\s\S]*?)<\/template>\s*<\/f-template>/g;
|
|
60
|
+
let match;
|
|
61
|
+
while ((match = regex.exec(html)) !== null) {
|
|
62
|
+
const name = match[1];
|
|
63
|
+
const attrs = match[2].trim();
|
|
64
|
+
const inner = match[3].trim();
|
|
65
|
+
|
|
66
|
+
if (attrs.length > 0) {
|
|
67
|
+
results.push({
|
|
68
|
+
name,
|
|
69
|
+
content: `<template ${attrs}>${inner}</template>`,
|
|
70
|
+
});
|
|
71
|
+
} else {
|
|
72
|
+
results.push({ name, content: inner });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Convert FAST template directives to webui syntax.
|
|
80
|
+
*
|
|
81
|
+
* - `<f-when value="{{expr}}">` → `<if condition="expr">`
|
|
82
|
+
* - `</f-when>` → `</if>`
|
|
83
|
+
* - `<f-repeat value="{{item in list}}" ...>` → `<for each="item in list" ...>`
|
|
84
|
+
* - `</f-repeat>` → `</for>`
|
|
85
|
+
*
|
|
86
|
+
* @param {string} html - Template HTML using FAST directive syntax.
|
|
87
|
+
* @returns {string} Template HTML using webui directive syntax.
|
|
88
|
+
*/
|
|
89
|
+
export function convertToWebuiSyntax(html) {
|
|
90
|
+
return html
|
|
91
|
+
.replace(
|
|
92
|
+
/<f-when\s+value="{{([\s\S]*?)}}"\s*>/g,
|
|
93
|
+
(_, expr) => `<if condition="${expr.trim()}">`,
|
|
94
|
+
)
|
|
95
|
+
.replace(/<\/f-when>/g, "</if>")
|
|
96
|
+
.replace(
|
|
97
|
+
/<f-repeat\s+value="{{([\s\S]*?)}}"([^>]*)>/g,
|
|
98
|
+
(_, expr, rest) => `<for each="${expr.trim()}"${rest}>`,
|
|
99
|
+
)
|
|
100
|
+
.replace(/<\/f-repeat>/g, "</for>");
|
|
101
|
+
}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { brotliCompressSync, gzipSync } from "node:zlib";
|
|
5
|
+
import { build } from "esbuild";
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const packageRoot = path.resolve(__dirname, "..");
|
|
10
|
+
const rootImportPath = "@microsoft/fast-element";
|
|
11
|
+
const fastElementImportPath = "@microsoft/fast-element/fast-element.js";
|
|
12
|
+
const updatesImportPath = "@microsoft/fast-element/updates.js";
|
|
13
|
+
const observableImportPath = "@microsoft/fast-element/observable.js";
|
|
14
|
+
const attrImportPath = "@microsoft/fast-element/attr.js";
|
|
15
|
+
const childrenImportPath = "@microsoft/fast-element/children.js";
|
|
16
|
+
const refImportPath = "@microsoft/fast-element/ref.js";
|
|
17
|
+
const slottedImportPath = "@microsoft/fast-element/slotted.js";
|
|
18
|
+
const volatileImportPath = "@microsoft/fast-element/volatile.js";
|
|
19
|
+
const whenImportPath = "@microsoft/fast-element/when.js";
|
|
20
|
+
const htmlImportPath = "@microsoft/fast-element/html.js";
|
|
21
|
+
const repeatImportPath = "@microsoft/fast-element/repeat.js";
|
|
22
|
+
const cssImportPath = "@microsoft/fast-element/css.js";
|
|
23
|
+
const declarativeImportPath = "@microsoft/fast-element/declarative.js";
|
|
24
|
+
const hydrationImportPath = "@microsoft/fast-element/hydration.js";
|
|
25
|
+
const arrayObserverImportPath = "@microsoft/fast-element/array-observer.js";
|
|
26
|
+
const observerMapImportPath = "@microsoft/fast-element/observer-map.js";
|
|
27
|
+
const attributeMapImportPath = "@microsoft/fast-element/attribute-map.js";
|
|
28
|
+
|
|
29
|
+
const namedExports = [{ name: "FASTElement", importPath: fastElementImportPath }];
|
|
30
|
+
|
|
31
|
+
const measuredExports = [
|
|
32
|
+
{
|
|
33
|
+
name: "Updates",
|
|
34
|
+
export: "Updates",
|
|
35
|
+
importPath: updatesImportPath,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: "Observable",
|
|
39
|
+
export: "Observable",
|
|
40
|
+
importPath: observableImportPath,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "observable",
|
|
44
|
+
export: "observable",
|
|
45
|
+
importPath: observableImportPath,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "attr",
|
|
49
|
+
export: "attr",
|
|
50
|
+
importPath: attrImportPath,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "children",
|
|
54
|
+
export: "children",
|
|
55
|
+
importPath: childrenImportPath,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "ref",
|
|
59
|
+
export: "ref",
|
|
60
|
+
importPath: refImportPath,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "slotted",
|
|
64
|
+
export: "slotted",
|
|
65
|
+
importPath: slottedImportPath,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: "volatile",
|
|
69
|
+
export: "volatile",
|
|
70
|
+
importPath: volatileImportPath,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "when",
|
|
74
|
+
export: "when",
|
|
75
|
+
importPath: whenImportPath,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "html",
|
|
79
|
+
export: "html",
|
|
80
|
+
importPath: htmlImportPath,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "repeat",
|
|
84
|
+
export: "repeat",
|
|
85
|
+
importPath: repeatImportPath,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: "css",
|
|
89
|
+
export: "css",
|
|
90
|
+
importPath: cssImportPath,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: "enableHydration",
|
|
94
|
+
export: "enableHydration",
|
|
95
|
+
importPath: hydrationImportPath,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "declarativeTemplate",
|
|
99
|
+
export: "declarativeTemplate",
|
|
100
|
+
importPath: declarativeImportPath,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: "ArrayObserver",
|
|
104
|
+
export: "ArrayObserver",
|
|
105
|
+
importPath: arrayObserverImportPath,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "observerMap",
|
|
109
|
+
export: "observerMap",
|
|
110
|
+
importPath: observerMapImportPath,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "attributeMap",
|
|
114
|
+
export: "attributeMap",
|
|
115
|
+
importPath: attributeMapImportPath,
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
function formatExportLabel(name, importPath) {
|
|
120
|
+
return `${name} (${importPath})`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function formatBytes(bytes) {
|
|
124
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
125
|
+
return `${(bytes / 1024).toFixed(2)} KB`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function measureBuffer(buffer) {
|
|
129
|
+
const gzip = gzipSync(buffer);
|
|
130
|
+
const brotli = brotliCompressSync(buffer);
|
|
131
|
+
return {
|
|
132
|
+
minified: buffer.length,
|
|
133
|
+
gzip: gzip.length,
|
|
134
|
+
brotli: brotli.length,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function measureExport(exportName, importPath = rootImportPath) {
|
|
139
|
+
const contents = `import { ${exportName} } from "${importPath}";
|
|
140
|
+
export { ${exportName} };
|
|
141
|
+
`;
|
|
142
|
+
|
|
143
|
+
const result = await build({
|
|
144
|
+
stdin: {
|
|
145
|
+
contents,
|
|
146
|
+
resolveDir: packageRoot,
|
|
147
|
+
loader: "ts",
|
|
148
|
+
},
|
|
149
|
+
bundle: true,
|
|
150
|
+
minify: true,
|
|
151
|
+
format: "esm",
|
|
152
|
+
write: false,
|
|
153
|
+
treeShaking: true,
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const code = Buffer.from(result.outputFiles[0].contents);
|
|
157
|
+
return measureBuffer(code);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function measureCore() {
|
|
161
|
+
const coreBundle = path.resolve(packageRoot, "dist/fast-element.min.js");
|
|
162
|
+
const buffer = readFileSync(coreBundle);
|
|
163
|
+
return measureBuffer(buffer);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async function main() {
|
|
167
|
+
const results = [];
|
|
168
|
+
|
|
169
|
+
// Measure CDN rollup bundle
|
|
170
|
+
const core = await measureCore();
|
|
171
|
+
results.push({ name: "CDN Rollup Bundle", ...core });
|
|
172
|
+
|
|
173
|
+
// Measure each named export in parallel
|
|
174
|
+
const exportResults = await Promise.all(
|
|
175
|
+
namedExports.map(async ({ name, importPath }) => {
|
|
176
|
+
const sizes = await measureExport(name, importPath);
|
|
177
|
+
return { name: formatExportLabel(name, importPath), ...sizes };
|
|
178
|
+
}),
|
|
179
|
+
);
|
|
180
|
+
results.push(...exportResults);
|
|
181
|
+
|
|
182
|
+
// Measure each root export in parallel
|
|
183
|
+
const measuredResults = await Promise.all(
|
|
184
|
+
measuredExports.map(
|
|
185
|
+
async ({ name, export: exportName, importPath = rootImportPath }) => {
|
|
186
|
+
const sizes = await measureExport(exportName, importPath);
|
|
187
|
+
return { name: formatExportLabel(name, importPath), ...sizes };
|
|
188
|
+
},
|
|
189
|
+
),
|
|
190
|
+
);
|
|
191
|
+
results.push(...measuredResults);
|
|
192
|
+
|
|
193
|
+
// Generate markdown table
|
|
194
|
+
const lines = [
|
|
195
|
+
"# Export Sizes",
|
|
196
|
+
"",
|
|
197
|
+
"Bundle sizes for `@microsoft/fast-element` exports.",
|
|
198
|
+
"",
|
|
199
|
+
"| Export | Minified | Gzip | Brotli |",
|
|
200
|
+
"|--------|----------|------|--------|",
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
for (const { name, minified, gzip, brotli } of results) {
|
|
204
|
+
lines.push(
|
|
205
|
+
`| ${name} | ${formatBytes(minified)} | ${formatBytes(gzip)} | ${formatBytes(brotli)} |`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
lines.push("");
|
|
210
|
+
|
|
211
|
+
const outputPath = path.resolve(packageRoot, "SIZES.md");
|
|
212
|
+
writeFileSync(outputPath, lines.join("\n"));
|
|
213
|
+
console.log(`Bundle sizes written to ${outputPath}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
main().catch(err => {
|
|
217
|
+
console.error(err);
|
|
218
|
+
process.exit(1);
|
|
219
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { fileURLToPath } from
|
|
4
|
-
import { Extractor, ExtractorConfig } from
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { Extractor, ExtractorConfig } from "@microsoft/api-extractor";
|
|
5
5
|
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = path.dirname(__filename);
|
|
@@ -10,17 +10,37 @@ export const exportPaths = [
|
|
|
10
10
|
{
|
|
11
11
|
path: "./context.js",
|
|
12
12
|
docsFolder: "context",
|
|
13
|
-
configPath: path.resolve(__dirname, "../api-extractor.context.json")
|
|
13
|
+
configPath: path.resolve(__dirname, "../api-extractor.context.json"),
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
path: "./declarative.js",
|
|
17
|
+
docsFolder: "declarative",
|
|
18
|
+
configPath: path.resolve(__dirname, "../api-extractor.declarative.json"),
|
|
14
19
|
},
|
|
15
20
|
{
|
|
16
21
|
path: "./di.js",
|
|
17
22
|
docsFolder: "di",
|
|
18
|
-
configPath: path.resolve(__dirname, "../api-extractor.di.json")
|
|
19
|
-
}
|
|
23
|
+
configPath: path.resolve(__dirname, "../api-extractor.di.json"),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
path: "./hydration.js",
|
|
27
|
+
docsFolder: "hydration",
|
|
28
|
+
configPath: path.resolve(__dirname, "../api-extractor.hydration.json"),
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
path: "./styles.js",
|
|
32
|
+
docsFolder: "styles",
|
|
33
|
+
configPath: path.resolve(__dirname, "../api-extractor.styles.json"),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
path: "./arrays.js",
|
|
37
|
+
docsFolder: "arrays",
|
|
38
|
+
configPath: path.resolve(__dirname, "../api-extractor.arrays.json"),
|
|
39
|
+
},
|
|
20
40
|
];
|
|
21
41
|
|
|
22
|
-
(function() {
|
|
23
|
-
exportPaths.forEach(
|
|
42
|
+
(function () {
|
|
43
|
+
exportPaths.forEach(exportPath => {
|
|
24
44
|
const docsFolder = path.resolve(__dirname, `../docs/${exportPath.docsFolder}`);
|
|
25
45
|
// Create folders in the docs directory
|
|
26
46
|
if (!fs.existsSync(docsFolder)) {
|
|
@@ -31,20 +51,19 @@ export const exportPaths = [
|
|
|
31
51
|
const extractorConfig = ExtractorConfig.loadFileAndPrepare(exportPath.configPath);
|
|
32
52
|
|
|
33
53
|
// Invoke API Extractor
|
|
34
|
-
const extractorResult = Extractor.invoke(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
localBuild: process.argv[2] !== "ci",
|
|
39
|
-
}
|
|
40
|
-
);
|
|
54
|
+
const extractorResult = Extractor.invoke(extractorConfig, {
|
|
55
|
+
// Equivalent to the "--local" command-line parameter
|
|
56
|
+
localBuild: process.argv[2] !== "ci",
|
|
57
|
+
});
|
|
41
58
|
|
|
42
59
|
if (extractorResult.succeeded) {
|
|
43
|
-
console.log(
|
|
44
|
-
|
|
60
|
+
console.log(
|
|
61
|
+
`API Extractor completed successfully for ${exportPath.configPath}`,
|
|
62
|
+
);
|
|
63
|
+
} else {
|
|
45
64
|
console.error(
|
|
46
|
-
|
|
47
|
-
|
|
65
|
+
`API Extractor completed with ${extractorResult.errorCount} errors` +
|
|
66
|
+
` and ${extractorResult.warningCount} warnings for ${exportPath.configPath}`,
|
|
48
67
|
);
|
|
49
68
|
}
|
|
50
69
|
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Fixtures
|
|
2
|
+
|
|
3
|
+
Fixtures are organized into category subdirectories:
|
|
4
|
+
|
|
5
|
+
| Category | Description |
|
|
6
|
+
|---|---|
|
|
7
|
+
| [`bindings/`](./bindings/README.md) | Various binding types (attribute, content, event, dot-syntax, host). |
|
|
8
|
+
| [`scenarios/`](./scenarios/README.md) | Complex scenarios with edge cases involving multiple features. |
|
|
9
|
+
| [`directives/`](./directives/README.md) | Attribute and element directives (`f-repeat`, `f-when`, `f-ref`, etc.). |
|
|
10
|
+
| [`extensions/`](./extensions/README.md) | Additional functionality that augments the core behavior (attribute maps, observer maps). |
|
|
11
|
+
| [`ecosystem/`](./ecosystem/README.md) | Other ecosystem APIs (errors, lifecycle, performance). |
|
|
12
|
+
|
|
13
|
+
Each fixture contains the following contents:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
<category>/<fixture-name>/
|
|
17
|
+
├── <fixture-name>.spec.ts - Playwright tests
|
|
18
|
+
├── entry.html - Entry template with root custom elements (input to build-fixtures.js)
|
|
19
|
+
├── fast-build.config.json - Build configuration for @microsoft/fast-build
|
|
20
|
+
├── index.html - Pre-rendered HTML page served by Vite (generated by build-fixtures.js)
|
|
21
|
+
├── main.ts - Component definition and setup
|
|
22
|
+
├── state.json - Initial state passed to the server-side renderer
|
|
23
|
+
└── templates.html - Declarative f-template definitions
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Fixtures are auto-discovered by the Vite config in `../vite.config.ts`. To add a new fixture, create a new directory within the appropriate category with the files above — no other changes are needed.
|
|
27
|
+
|
|
28
|
+
## Hydration readiness
|
|
29
|
+
|
|
30
|
+
Fixtures that exercise prerendered Declarative Shadow DOM should enable
|
|
31
|
+
hydration explicitly and set a global flag in the `hydrationComplete()` callback
|
|
32
|
+
so Playwright tests can wait for the element to be fully interactive before
|
|
33
|
+
asserting. The standard pattern is:
|
|
34
|
+
|
|
35
|
+
1. **In `main.ts`**, call `enableHydration()` before elements connect:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { enableHydration } from "@microsoft/fast-element/hydration.js";
|
|
39
|
+
|
|
40
|
+
enableHydration({
|
|
41
|
+
hydrationComplete() {
|
|
42
|
+
(window as any).hydrationCompleted = true;
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Per-element callbacks belong on `declarativeTemplate(callbacks)`. Map
|
|
48
|
+
behavior belongs in define extensions such as `attributeMap()` and
|
|
49
|
+
`observerMap()`.
|
|
50
|
+
|
|
51
|
+
2. **In the spec file**, create the wait **before** navigation so the listener is registered before the page starts loading:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const hydrationCompleted = page.waitForFunction(
|
|
55
|
+
() => (window as any).hydrationCompleted === true,
|
|
56
|
+
);
|
|
57
|
+
await page.goto("/fixtures/<fixture-name>/");
|
|
58
|
+
await hydrationCompleted;
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Place this around every `page.goto()` call — including inside `test.beforeEach` hooks — to prevent assertions from running before hydration finishes.
|
|
62
|
+
|
|
63
|
+
## Entry HTML attribute guidelines
|
|
64
|
+
|
|
65
|
+
The `entry.html` file defines the root custom elements that the server-side renderer processes. When writing attribute bindings on root elements, follow these conventions:
|
|
66
|
+
|
|
67
|
+
- **Same-name complex bindings are unnecessary.** Attributes like `list="{{list}}"` where `list` is an array or object are redundant — non-primitive values are automatically stripped from the rendered opening tag, and state propagation already provides the value to the element's template. Omit these attributes.
|
|
68
|
+
- **Rename bindings should be avoided.** Prefer naming state properties to match the attribute name the element expects. When a rename such as `foo="{{bar}}"` is removed, ensure `state.json` includes a property named `foo` with the contents of `bar` so the value is available via state propagation.
|
|
69
|
+
- **Property bindings (`:attr`) for renames are acceptable** when multiple instances of the same element in a fixture need different values for the same property (e.g., `:items="{{emptyItems}}"` and `:items="{{singleItem}}"` on separate elements).
|
|
70
|
+
- **Primitive same-name bindings are fine.** Attributes like `type="{{type}}"` where the value is a string, number, or boolean are rendered onto the opening tag and may be needed for `@attr`-based element initialization.
|
|
71
|
+
|
|
72
|
+
For a complete guide on creating fixtures — including how to write each file, component patterns, and spec examples — see [WRITING_FIXTURES.md](./WRITING_FIXTURES.md).
|