diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f8a84e735df..97282b0ecf5 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -16,25 +16,26 @@ FAST (`@microsoft/fast`) is a Microsoft open-source monorepo for building W3C-st ## Packages +Each package includes a DESIGN.md file, read that to gain a general understanding of the code for that package. + | Package | Status | Purpose | |---|---|---| | `@microsoft/fast-element` | Stable (v2) | Core Web Component library | | `@microsoft/fast-html` | Alpha | Declarative HTML parser | | `@microsoft/fast-router` | Alpha | Web Component router | | `@microsoft/fast-build` | Prerelease | Declarative HTML server side renderer | +| `@microsoft/fast-test-harness` | Prerelease | Testing utilities for FASTElement components | -### Other packages +### Sites | Package | Status | Purpose | |---|---|---| -| `@microsoft/fast-bench` | Private (not published as a package) | Benchmarking utilities | | `sites/website` | Private (not published as a package) | Documentation website source | -| `@microsoft/fast-ssr` | Alpha (not actively maintained) | Server-side rendering utilities | +| `sites/benchmarks` | Private (not published as a package) | Benchmarking site | ### Example projects - `examples/todo-app/` — A simple To-Do app demonstrating FAST usage patterns. -- `examples/ssr/` — Server-side rendering example using `@microsoft/fast-ssr`. ## Skills @@ -93,7 +94,8 @@ packages// ``` - Source files use **kebab-case**: `element-controller.ts`, `update-queue.ts`. -- Test files use `*.pw.spec.ts` suffix, co-located next to the source they test. +- Playwright test files use `*.pw.spec.ts` suffix, co-located next to the source they test. +- Node test files use `*.spec.ts` suffix. ## Code Style @@ -152,3 +154,5 @@ Before finishing any change, run these commands from the monorepo root and confi - [ ] `npm run test` — all tests pass - [ ] `npm run biome:check` — Biome linting and formatting pass - [ ] `npm run checkchange` — beachball change files exist for any `packages/*` changes + +Read the [shipping skill](./skills/shipping/SKILL.md) and ensure you have updated everything outlined in that file. diff --git a/.github/skills/shipping/SKILL.md b/.github/skills/shipping/SKILL.md index 13a0d0262ec..a5b59ef85db 100644 --- a/.github/skills/shipping/SKILL.md +++ b/.github/skills/shipping/SKILL.md @@ -180,9 +180,7 @@ If the breaking change is significant or requires multiple PRs, open a [discussi # Documentation -Keep the website documentation in `sites/website/src/docs/` updated when making changes that affect public APIs, behavior, or usage patterns. The documentation is organized by version: - -- `sites/website/src/docs/2.x/` — Current version documentation (getting started, guides, advanced topics, API reference). +After any changes ensure that the documentation is up to date, this includes the files DESIGN.md and README.md files for any packages/crates that have been modified. If your changes update or add to the public API, update the sites/website/src/docs/ files. Only update the latest version, these are denoted by major versions in their folder names inside the docs folder, 1.x, 2.x, etc., find the latest version of the docs and modify them if necessary. When adding or modifying exported APIs, run the website prebuild script to regenerate API documentation from the api-extractor output: diff --git a/.github/workflows/cd-gh-pages.yml b/.github/workflows/cd-gh-pages.yml index 7803cb74c27..8ad05f43742 100644 --- a/.github/workflows/cd-gh-pages.yml +++ b/.github/workflows/cd-gh-pages.yml @@ -13,18 +13,16 @@ permissions: jobs: build: runs-on: ubuntu-latest - strategy: - matrix: - node: [22.x] steps: - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 with: - node-version: ${{ matrix.node-version }} fetch-depth: 0 + - uses: actions/setup-node@v6 + with: + node-version: 22 + - name: Set Git User run: | git config --global user.name "${{ env.GITHUB_SERVICE_USER }}" diff --git a/.github/workflows/ci-validate-platforms.yml b/.github/workflows/ci-validate-platforms.yml index bc35f42893b..68615481900 100644 --- a/.github/workflows/ci-validate-platforms.yml +++ b/.github/workflows/ci-validate-platforms.yml @@ -74,11 +74,11 @@ jobs: run: cargo install wasm-pack - name: Build workspaces - run: npx lage build ${{ github.event_name == 'pull_request' && '--since origin/main' || '' }} + run: npx lage build ${{ github.event_name == 'pull_request' && '--since origin/main' || '' }} --allow-no-target-runs - name: Install playwright dependencies and browsers run: | npx playwright install --with-deps - name: Run tests in all Packages - run: npx lage test:node test:playwright ${{ github.event_name == 'pull_request' && '--since origin/main' || '' }} + run: npx lage test:node test:playwright ${{ github.event_name == 'pull_request' && '--since origin/main' || '' }} --allow-no-target-runs diff --git a/.github/workflows/ci-validate-pr.yml b/.github/workflows/ci-validate-pr.yml index 4c693ab7448..3e12f8927f9 100644 --- a/.github/workflows/ci-validate-pr.yml +++ b/.github/workflows/ci-validate-pr.yml @@ -58,14 +58,14 @@ jobs: run: cargo install wasm-pack - name: Build workspaces - run: npx lage build ${{ github.event_name == 'pull_request' && format('--since origin/{0}', github.event.pull_request.base.ref) || '' }} + run: npx lage build ${{ github.event_name == 'pull_request' && format('--since origin/{0}', github.event.pull_request.base.ref) || '' }} --allow-no-target-runs - name: Install playwright dependencies and browsers run: | npx playwright install --with-deps - name: Testing unit tests - run: npx lage test:node test:chromium ${{ github.event_name == 'pull_request' && format('--since origin/{0}', github.event.pull_request.base.ref) || '' }} + run: npx lage test:node test:chromium ${{ github.event_name == 'pull_request' && format('--since origin/{0}', github.event.pull_request.base.ref) || '' }} --allow-no-target-runs - name: Testing final validation run: npm run test:validation diff --git a/change/@microsoft-fast-element-5636cb6f-65c6-4c40-b964-d6c4b4b054f6.json b/change/@microsoft-fast-element-5636cb6f-65c6-4c40-b964-d6c4b4b054f6.json new file mode 100644 index 00000000000..f468ccd0591 --- /dev/null +++ b/change/@microsoft-fast-element-5636cb6f-65c6-4c40-b964-d6c4b4b054f6.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "chore: replace rollup-plugin-filesize with esbuild bundle size reporting", + "packageName": "@microsoft/fast-element", + "email": "7559015+janechu@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/examples/ssr/CHANGELOG.json b/examples/ssr/CHANGELOG.json deleted file mode 100644 index 5e9873a0e4b..00000000000 --- a/examples/ssr/CHANGELOG.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "fast-ssr", - "entries": [ - { - "date": "Wed, 22 Jun 2022 20:17:50 GMT", - "tag": "fast-ssr_v1.0.0", - "version": "1.0.0", - "comments": { - "prerelease": [ - { - "comment": "Bump @microsoft/fast-ssr to v1.0.0-beta.4", - "author": "nicholasrice@users.noreply.github.com", - "commit": "f28cdb9fdba9cb27904acfad7444de82d447f39e", - "package": "fast-ssr" - } - ] - } - } - ] -} diff --git a/examples/ssr/CHANGELOG.md b/examples/ssr/CHANGELOG.md deleted file mode 100644 index 1e74f733696..00000000000 --- a/examples/ssr/CHANGELOG.md +++ /dev/null @@ -1,13 +0,0 @@ -# Change Log - fast-ssr - -This log was last generated on Wed, 22 Jun 2022 20:17:50 GMT and should not be manually modified. - - - -## 1.0.0 - -Wed, 22 Jun 2022 20:17:50 GMT - -### Changes - -- Bump @microsoft/fast-ssr to v1.0.0-beta.4 (nicholasrice@users.noreply.github.com) diff --git a/examples/ssr/README.md b/examples/ssr/README.md deleted file mode 100644 index d2bb1c7b93f..00000000000 --- a/examples/ssr/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Server-Side Rendering (SSR) Tutorial - -An SSR implementation of the Todo App Tutorial. All components are defined by the [Todo App tutorial](../todo-app/), and the SSR implementation exists in [server.js](./server.js) - -## Running the experience - -To build the app and start the web server, run `npm start`. diff --git a/examples/ssr/package.json b/examples/ssr/package.json deleted file mode 100644 index 9fae1024e57..00000000000 --- a/examples/ssr/package.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "name": "@microsoft/fast-ssr-example", - "version": "1.0.0", - "description": "", - "main": "dist/exports.js", - "type": "module", - "private": true, - "scripts": { - "build": "vite build", - "watch": "tsc -p tsconfig.json --watch", - "start": "npm run build && node server.js", - "test": "npm run build" - }, - "author": { - "name": "Microsoft", - "url": "https://discord.gg/FcSNfg4" - }, - "homepage": "https://www.fast.design/", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/Microsoft/fast.git", - "directory": "examples/ssr" - }, - "dependencies": { - "@microsoft/fast-element": "^2.10.4", - "@microsoft/fast-ssr": "^1.0.0-beta.40", - "@microsoft/fast-todo-app-example": "1.0.0" - } -} diff --git a/examples/ssr/server.js b/examples/ssr/server.js deleted file mode 100644 index 43c37223fdd..00000000000 --- a/examples/ssr/server.js +++ /dev/null @@ -1,63 +0,0 @@ -/* eslint-disable no-undef */ -import "@microsoft/fast-ssr/install-dom-shim.js"; -import fs from "fs"; -import { html } from "@microsoft/fast-element"; -import fastSSR, { - DeclarativeShadowDOMPolyfill, - RequestStorageManager, -} from "@microsoft/fast-ssr"; -import express from "express"; -import { DefaultTodoList, app as todoApp, TodoList } from "@microsoft/fast-todo-app-example"; - -const app = express(); -const port = 8080; -const { templateRenderer } = fastSSR(); - -todoApp.define(); - -app.use(RequestStorageManager.middleware()); -app.use(express.static("./www")); - -const template = html` - - - - - - SSR Example - - - - - - - - - -`; - -app.get("/", (req, res) => { - const todoData = JSON.parse(fs.readFileSync("./todo-data.json").toString()); - TodoList.provide(document, new DefaultTodoList(todoData)); - - const stream = templateRenderer.render( - template, - templateRenderer.createRenderInfo(), - ); - - for (const part of stream) { - res.write(part); - } - - res.end(); -}); - -app.listen(port, () => { - console.log(`SSR example app listening on port ${port}`); -}); diff --git a/examples/ssr/src/main.ts b/examples/ssr/src/main.ts deleted file mode 100644 index 91f51f61dc8..00000000000 --- a/examples/ssr/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { app, DefaultTodoList, TodoList } from "@microsoft/fast-todo-app-example"; - -const SSRState = (window as any).__SSR_STATE__ || []; - -TodoList.provide(document, new DefaultTodoList(SSRState)); -app.define(); diff --git a/examples/ssr/todo-data.json b/examples/ssr/todo-data.json deleted file mode 100644 index c0877f5bb39..00000000000 --- a/examples/ssr/todo-data.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "description": "pick up groceries", - "done": true - }, - { - "description": "schedule baby-sitter", - "done": true - }, - { - "description": "schedule vet appointment", - "done": false - } -] \ No newline at end of file diff --git a/examples/ssr/tsconfig.json b/examples/ssr/tsconfig.json deleted file mode 100644 index c3e15714230..00000000000 --- a/examples/ssr/tsconfig.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2015", - "module": "ES2015", - "moduleResolution": "bundler", - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "noEmitOnError": true, - "strict": true, - "outDir": "dist", - "rootDir": "src", - "lib": [ - "dom", - ], - "types": [ - "express" - ] - }, - "include": [ - "src" - ] -} diff --git a/examples/ssr/vite.config.ts b/examples/ssr/vite.config.ts deleted file mode 100644 index 46573b410d3..00000000000 --- a/examples/ssr/vite.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { defineConfig } from "vite"; - -export default defineConfig({ - build: { - outDir: "www", - emptyOutDir: true, - sourcemap: true, - rollupOptions: { - input: "src/main.ts", - output: { - entryFileNames: "bundle.js", - }, - }, - }, -}); diff --git a/package-lock.json b/package-lock.json index e47196b67a3..71afa348775 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,8 @@ "workspaces": [ "build", "packages/*", - "sites/website", - "examples/todo-app", - "examples/ssr" + "sites/*", + "examples/*" ], "devDependencies": { "@ast-grep/cli": "0.37.0", @@ -32,7 +31,6 @@ "lage": "2.15.8", "lefthook": "2.1.4", "rollup": "4.59.0", - "rollup-plugin-filesize": "10.0.0", "typescript": "5.3.3", "vite": "7.3.2", "yargs": "17.7.2" @@ -50,16 +48,6 @@ "clean": "clean.mjs" } }, - "examples/ssr": { - "name": "@microsoft/fast-ssr-example", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "@microsoft/fast-element": "^2.10.4", - "@microsoft/fast-ssr": "^1.0.0-beta.40", - "@microsoft/fast-todo-app-example": "1.0.0" - } - }, "examples/todo-app": { "name": "@microsoft/fast-todo-app-example", "version": "1.0.0", @@ -656,16 +644,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", - "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@biomejs/biome": { "version": "2.4.8", "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.8.tgz", @@ -1335,16 +1313,6 @@ "node": ">=18" } }, - "node_modules/@gar/promise-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", - "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/@genesiscommunitysuccess/cep-fast-plugin": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@genesiscommunitysuccess/cep-fast-plugin/-/cep-fast-plugin-5.0.3.tgz", @@ -1415,9 +1383,9 @@ } }, "node_modules/@github/catalyst": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@github/catalyst/-/catalyst-1.8.0.tgz", - "integrity": "sha512-uLpi/D/mKfylYaFLfzNuloXNENi0AlcM0Z7hwYLH8Z030jBCr+ueMdX2xLxCzpMH/keYXKh0uPrHSMfcbxU6KA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@github/catalyst/-/catalyst-1.8.1.tgz", + "integrity": "sha512-dnN4WWpbeuQvA17LvsGdlXEueJdBk9y+I+WO5pdNpoHNOXPsFcz3hJrq1iRmdsNgQOf4S8e83axtwIxvG62eWA==", "dev": true, "license": "MIT" }, @@ -1439,19 +1407,6 @@ "node": ">=12" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1555,7 +1510,7 @@ } }, "node_modules/@microsoft/fast-bench": { - "resolved": "packages/bench", + "resolved": "sites/benchmarks", "link": true }, "node_modules/@microsoft/fast-build": { @@ -1582,14 +1537,6 @@ "resolved": "sites/website", "link": true }, - "node_modules/@microsoft/fast-ssr": { - "resolved": "packages/fast-ssr", - "link": true - }, - "node_modules/@microsoft/fast-ssr-example": { - "resolved": "examples/ssr", - "link": true - }, "node_modules/@microsoft/fast-test-harness": { "resolved": "packages/fast-test-harness", "link": true @@ -1617,9 +1564,9 @@ } }, "node_modules/@microsoft/webui": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@microsoft/webui/-/webui-0.0.9.tgz", - "integrity": "sha512-jAV7GiTeICbuAhNmwc5Fyf07oNGcRqbsqrC8DqUM0P6yxqnFTt1PmB/VzTP8NhMVxufaqGcy2qY6QueG9Asypg==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@microsoft/webui/-/webui-0.0.10.tgz", + "integrity": "sha512-lGj0PyVoYUOOJ1MWhseGSe5ZJQurp7KWvSgYtNMBiAb140rD2MXQsHwbwIPsqEPFPtqtCZcxuNzbDqJ7Bl8gRQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -1630,18 +1577,18 @@ "node": ">=18" }, "optionalDependencies": { - "@microsoft/webui-darwin-arm64": "0.0.9", - "@microsoft/webui-darwin-x64": "0.0.9", - "@microsoft/webui-linux-arm64": "0.0.9", - "@microsoft/webui-linux-x64": "0.0.9", - "@microsoft/webui-win32-arm64": "0.0.9", - "@microsoft/webui-win32-x64": "0.0.9" + "@microsoft/webui-darwin-arm64": "0.0.10", + "@microsoft/webui-darwin-x64": "0.0.10", + "@microsoft/webui-linux-arm64": "0.0.10", + "@microsoft/webui-linux-x64": "0.0.10", + "@microsoft/webui-win32-arm64": "0.0.10", + "@microsoft/webui-win32-x64": "0.0.10" } }, "node_modules/@microsoft/webui-darwin-arm64": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@microsoft/webui-darwin-arm64/-/webui-darwin-arm64-0.0.9.tgz", - "integrity": "sha512-91HprvaitU62IzdYgt22qMCiEXvr0Utg9vxUc6Mt3mh4KVfSsFVmN7Z6J7eXZQ858CEW4xXKSfpeiEXKkpNGSg==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@microsoft/webui-darwin-arm64/-/webui-darwin-arm64-0.0.10.tgz", + "integrity": "sha512-ApVNle/cU++YYeSG1qiyyP6wC2B5lxPhoKUZI8KZlPLViTwgrJ9Th37HhPqvCPqLMnY06jYtAQlPXbjGZxCNsQ==", "cpu": [ "arm64" ], @@ -1653,9 +1600,9 @@ ] }, "node_modules/@microsoft/webui-darwin-x64": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@microsoft/webui-darwin-x64/-/webui-darwin-x64-0.0.9.tgz", - "integrity": "sha512-JDVmFki6CRRpj+F9CNTPI+b67fIQicLn3AmUQLFFCp0JQqaeGwpdUmXjzPy/Am+dQDCYVL4bKOeysmz4pHDDMA==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@microsoft/webui-darwin-x64/-/webui-darwin-x64-0.0.10.tgz", + "integrity": "sha512-BfKIrhqNDFWA1UZPLccZGq1LEDbA8pNEAsJXaaidAFdzB6Mwhezk9tTKArATthctBOd8O9k5sx5rm7+5FnE15A==", "cpu": [ "x64" ], @@ -1667,9 +1614,9 @@ ] }, "node_modules/@microsoft/webui-linux-arm64": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@microsoft/webui-linux-arm64/-/webui-linux-arm64-0.0.9.tgz", - "integrity": "sha512-fGcSTZi3QfqtdTXsGkSVQ8JT8o4gLpx/32i10qCxf/FvVxkxs7DosgjXgl7lx+kJ2XuTqCOCbSrLLjIK8T/WdA==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@microsoft/webui-linux-arm64/-/webui-linux-arm64-0.0.10.tgz", + "integrity": "sha512-D5gg78/s3QEph3zwcL7PxaHEp33r7EIX2/CpzVXhYq+nTE50Kx3MYQVkyVoSFCp80dz8NpgEB771/JeFGOQ3lQ==", "cpu": [ "arm64" ], @@ -1681,9 +1628,9 @@ ] }, "node_modules/@microsoft/webui-linux-x64": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@microsoft/webui-linux-x64/-/webui-linux-x64-0.0.9.tgz", - "integrity": "sha512-w4AtqZevHbf+AUSMuSq0388DPfZEDi0DoajxVdNas5NBZ8qEr4d/2iP0VSx1vMBcH7nIPHjzM7DJnr9rYnt4Mw==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@microsoft/webui-linux-x64/-/webui-linux-x64-0.0.10.tgz", + "integrity": "sha512-RCnwb7F6Wf75LYDnva/vIN0sNEuKRAXS5BEL8Yg5LuoZtncTGctGxSvMoqhLbBAeD4nnlhTyLn/ZFQVRWJluGw==", "cpu": [ "x64" ], @@ -1695,9 +1642,9 @@ ] }, "node_modules/@microsoft/webui-win32-arm64": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@microsoft/webui-win32-arm64/-/webui-win32-arm64-0.0.9.tgz", - "integrity": "sha512-nNl7yvIu7uZ2y0/ViJ9tpOwflB0sqd1hHF0P53PK8dBfT7bqhby+UNv6tLAFjUYiu1xjnpTje8QIeQZKh2+Qow==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@microsoft/webui-win32-arm64/-/webui-win32-arm64-0.0.10.tgz", + "integrity": "sha512-dFHzxCCOhEPX9kC64uWvw3gV5ldeVdlQ2QreAHt/ewlnOQQmUFWQpzJaSWwirEezWwE20+uakECSt65LBnRuxQ==", "cpu": [ "arm64" ], @@ -1709,9 +1656,9 @@ ] }, "node_modules/@microsoft/webui-win32-x64": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/@microsoft/webui-win32-x64/-/webui-win32-x64-0.0.9.tgz", - "integrity": "sha512-FH4gprnUnNcEYgDkPHQS9D8h9gRQqYiy5Wswkgi75EgcELg2k8usGERexLOl/nmLMv4E3su7alhDKQm5oMXIJQ==", + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@microsoft/webui-win32-x64/-/webui-win32-x64-0.0.10.tgz", + "integrity": "sha512-9nrveoR0Cu9ZRAlXdGh1SI6ljSRwhWSlDj2vAmf4XAWSA4P5nOwL7krQtX/QTbj3xjytTC5t6vxOvASJdqCnSg==", "cpu": [ "x64" ], @@ -1760,269 +1707,6 @@ "node": ">= 8" } }, - "node_modules/@npmcli/agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.0.tgz", - "integrity": "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==", - "dev": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^11.2.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/agent/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@npmcli/fs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", - "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", - "dev": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/git": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", - "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promise-retry": "^1.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "ini": "^6.0.0", - "lru-cache": "^11.2.1", - "npm-pick-manifest": "^11.0.1", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "which": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/git/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=20" - } - }, - "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@npmcli/git/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/installed-package-contents": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", - "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^5.0.0", - "npm-normalize-package-bin": "^5.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/node-gyp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", - "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/package-json": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.5.tgz", - "integrity": "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "glob": "^13.0.0", - "hosted-git-info": "^9.0.0", - "json-parse-even-better-errors": "^5.0.0", - "proc-log": "^6.0.0", - "semver": "^7.5.3", - "spdx-expression-parse": "^4.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/package-json/node_modules/json-parse-even-better-errors": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", - "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/package-json/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@npmcli/package-json/node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/promise-spawn": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", - "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "which": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/promise-spawn/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=20" - } - }, - "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/redact": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", - "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/run-script": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.4.tgz", - "integrity": "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^5.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "node-gyp": "^12.1.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2555,86 +2239,6 @@ "string-argv": "~0.3.1" } }, - "node_modules/@sigstore/bundle": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", - "integrity": "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.5.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.0.tgz", - "integrity": "sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/protobuf-specs": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.1.tgz", - "integrity": "sha512-/ScWUhhoFasJsSRGTVBwId1loQjjnjAfE4djL6ZhrXRpNCmPTnUKF5Jokd58ILseOMjzET3UrMOtJPS9sYeI0g==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@sigstore/sign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz", - "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@gar/promise-retry": "^1.0.2", - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.2.0", - "@sigstore/protobuf-specs": "^0.5.0", - "make-fetch-happen": "^15.0.4", - "proc-log": "^6.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/tuf": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz", - "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.5.0", - "tuf-js": "^4.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/verify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.0.tgz", - "integrity": "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/@sindresorhus/slugify": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", @@ -2666,30 +2270,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", - "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@tufjs/models": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-4.1.0.tgz", - "integrity": "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^10.1.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/@types/argparse": { "version": "1.0.38", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", @@ -2772,13 +2352,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/parse5": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", - "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/qs": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", @@ -2847,16 +2420,6 @@ "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", "license": "MIT" }, - "node_modules/abbrev": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", - "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -2895,16 +2458,6 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/ajv": { "version": "8.18.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", @@ -2952,65 +2505,10 @@ } } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -3252,92 +2750,6 @@ "dev": true, "license": "ISC" }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/boxen/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/brace-expansion": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", @@ -3363,19 +2775,6 @@ "node": ">=8" } }, - "node_modules/brotli-size": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz", - "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "0.1.1" - }, - "engines": { - "node": ">= 10.16.0" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3392,73 +2791,6 @@ "node": ">= 0.8" } }, - "node_modules/cacache": { - "version": "20.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.4.tgz", - "integrity": "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^5.0.0", - "fs-minipass": "^3.0.0", - "glob": "^13.0.0", - "lru-cache": "^11.1.0", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^13.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "13.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", - "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.2.2", - "minipass": "^7.1.3", - "path-scurry": "^2.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/cacache/node_modules/path-scurry": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", - "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -3498,19 +2830,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -3565,29 +2884,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -3686,16 +2982,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/command-line-args": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.2.tgz", @@ -4050,12 +3336,6 @@ "node": ">= 0.4" } }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha512-sxNZ+ljy+RA1maXoUReeqBBpBC6RLKmg5ewzV+x+mSETmWNoKdZN6vcQjpFROemza23hGFskJtFNoUWUaQ+R4Q==", - "dev": true - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -4107,13 +3387,6 @@ "node": ">=6" } }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, "node_modules/errno": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/errno/-/errno-1.0.0.tgz", @@ -4323,13 +3596,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/express": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", @@ -4455,16 +3721,6 @@ } } }, - "node_modules/filesize": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz", - "integrity": "sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -4581,23 +3837,10 @@ "node": ">=14.14" } }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4678,9 +3921,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.13.7", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", - "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz", + "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==", "dev": true, "license": "MIT", "dependencies": { @@ -4947,29 +4190,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gzip-size/node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4992,9 +4212,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -5013,29 +4233,6 @@ "he": "bin/he" } }, - "node_modules/hosted-git-info": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz", - "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^11.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz", - "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, "node_modules/htmlparser2": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", @@ -5119,13 +4316,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, "node_modules/http-equiv-refresh": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-2.0.1.tgz", @@ -5155,84 +4345,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/http-proxy-agent/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/http-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -5266,19 +4378,6 @@ "node": ">= 4" } }, - "node_modules/ignore-walk": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", - "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minimatch": "^10.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -5311,26 +4410,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/ini": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", - "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -5470,12 +4549,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "license": "MIT" - }, "node_modules/is-ssh": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.4.1.tgz", @@ -5576,9 +4649,9 @@ "license": "MIT" }, "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -5587,16 +4660,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, "node_modules/junk": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", @@ -5824,9 +4887,9 @@ } }, "node_modules/liquidjs": { - "version": "10.25.5", - "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.25.5.tgz", - "integrity": "sha512-GKiKeZjJDdVoQAu+S9rzkYsYnYhcep5W3WwZXgb5f+yq484P/k9JqamBbGYu+LBEixcUAXZr2jogdAIjB3ki1w==", + "version": "10.25.6", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.25.6.tgz", + "integrity": "sha512-h5ki5HS1PiL9/NmLw3iUcTF1jQswKJd8KLEXNrtSf8XHF0v3c5+d+8llz3N9I5IUdc5rsOuVLb9AVnqvqqscPg==", "license": "MIT", "dependencies": { "commander": "^10.0.0" @@ -5888,40 +4951,6 @@ "node": ">=12" } }, - "node_modules/make-fetch-happen": { - "version": "15.0.5", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.5.tgz", - "integrity": "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promise-retry": "^1.0.0", - "@npmcli/agent": "^4.0.0", - "@npmcli/redact": "^4.0.0", - "cacache": "^20.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^6.0.0", - "ssri": "^13.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/make-fetch-happen/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/markdown-it": { "version": "14.1.1", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", @@ -6133,147 +5162,6 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-fetch": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.2.tgz", - "integrity": "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^2.0.0", - "minizlib": "^3.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - }, - "optionalDependencies": { - "iconv-lite": "^0.7.2" - } - }, - "node_modules/minipass-fetch/node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", - "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-sized": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-2.0.0.tgz", - "integrity": "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", @@ -6320,57 +5208,6 @@ "node": ">= 0.6" } }, - "node_modules/node-gyp": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.2.0.tgz", - "integrity": "sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^15.0.0", - "nopt": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "tar": "^7.5.4", - "tinyglobby": "^0.2.12", - "which": "^6.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", - "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=20" - } - }, - "node_modules/node-gyp/node_modules/which": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", - "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^4.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/node-html-parser": { "version": "6.1.13", "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-6.1.13.tgz", @@ -6393,22 +5230,6 @@ "esm-import-transformer": "^3.0.3" } }, - "node_modules/nopt": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", - "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^4.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6418,108 +5239,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-bundled": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", - "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^5.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-install-checks": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", - "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-package-arg": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", - "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", - "dev": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^7.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-packlist": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.4.tgz", - "integrity": "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==", - "dev": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^8.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-pick-manifest": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", - "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^8.0.0", - "npm-normalize-package-bin": "^5.0.0", - "npm-package-arg": "^13.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-registry-fetch": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", - "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^4.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^15.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^13.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -6604,15 +5323,6 @@ "node": ">= 0.8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -6652,19 +5362,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -6672,38 +5369,6 @@ "dev": true, "license": "BlueOak-1.0.0" }, - "node_modules/pacote": { - "version": "21.3.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.3.0.tgz", - "integrity": "sha512-8szw+HT7q/WsJjdpkkIUudWge9sUAI3LBDPJdBRh2HD8IrE3lAY+90nScTK+Ln95kRlcz/BOLEoY14qM0DIcvw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "@npmcli/installed-package-contents": "^4.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "@npmcli/run-script": "^10.0.0", - "cacache": "^20.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^13.0.0", - "npm-packlist": "^10.0.1", - "npm-pick-manifest": "^11.0.1", - "npm-registry-fetch": "^19.0.0", - "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^4.0.0", - "ssri": "^13.0.0", - "tar": "^7.4.3" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6766,12 +5431,6 @@ "node": ">=14.13.0" } }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "license": "MIT" - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -6879,6 +5538,20 @@ "node": ">=18" } }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -6889,9 +5562,9 @@ } }, "node_modules/postcss": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", - "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", + "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", "funding": [ { "type": "opencollective", @@ -6974,30 +5647,6 @@ "node": ">=6" } }, - "node_modules/proc-log": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", - "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -7215,16 +5864,6 @@ "node": ">=8" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -7254,99 +5893,30 @@ "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-filesize": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-filesize/-/rollup-plugin-filesize-10.0.0.tgz", - "integrity": "sha512-JAYYhzCcmGjmCzo3LEHSDE3RAPHKIeBdpqRhiyZSv5o/3wFhktUOzYAWg/uUKyEu5dEaVaql6UOmaqHx1qKrZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.13.8", - "boxen": "^5.0.0", - "brotli-size": "4.0.0", - "colors": "1.4.0", - "filesize": "^6.1.0", - "gzip-size": "^6.0.0", - "pacote": "^15.1.1", - "terser": "^5.6.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/router/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/router/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/router/node_modules/path-to-regexp": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", - "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" } }, "node_modules/run-parallel": { @@ -7641,24 +6211,6 @@ "dev": true, "license": "ISC" }, - "node_modules/sigstore": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", - "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.1.0", - "@sigstore/tuf": "^4.0.1", - "@sigstore/verify": "^3.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -7684,17 +6236,6 @@ "node": ">=8.0.0" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, "node_modules/smob": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/smob/-/smob-1.6.1.tgz", @@ -7705,61 +6246,6 @@ "node": ">=20.0.0" } }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/socks-proxy-agent/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socks-proxy-agent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7790,50 +6276,12 @@ "source-map": "^0.6.0" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", - "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", - "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", - "dev": true, - "license": "CC0-1.0" - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, - "node_modules/ssri": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.1.tgz", - "integrity": "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -8015,23 +6463,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tar": { - "version": "7.5.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz", - "integrity": "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/terser": { "version": "5.46.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.1.tgz", @@ -8111,59 +6542,6 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/tuf-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", - "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "4.1.0", - "debug": "^4.4.3", - "make-fetch-happen": "^15.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/tuf-js/node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/tuf-js/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -8256,16 +6634,6 @@ "node": ">= 0.4.0" } }, - "node_modules/validate-npm-package-name": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", - "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -8349,20 +6717,6 @@ } } }, - "node_modules/vite/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8379,64 +6733,6 @@ "node": ">= 8" } }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/workspace-tools": { "version": "0.40.4", "resolved": "https://registry.npmjs.org/workspace-tools/-/workspace-tools-0.40.4.tgz", @@ -8548,12 +6844,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, "node_modules/ws": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", @@ -8585,16 +6875,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -8682,14 +6962,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/bench": { - "name": "@microsoft/fast-bench", - "version": "0.0.0", - "dependencies": { - "@microsoft/fast-element": "*", - "@microsoft/fast-html": "*" - } - }, "packages/fast-build": { "name": "@microsoft/fast-build", "version": "0.4.0", @@ -8708,12 +6980,12 @@ }, "packages/fast-html": { "name": "@microsoft/fast-html", - "version": "1.0.0-alpha.49", + "version": "1.0.0-alpha.50", "license": "MIT", "devDependencies": { "@microsoft/fast-build": "^0.4.0", "@microsoft/fast-element": "^2.10.4", - "@microsoft/webui": "0.0.9" + "@microsoft/webui": "0.0.10" }, "peerDependencies": { "@microsoft/fast-element": "^2.10.4" @@ -8733,23 +7005,6 @@ "@microsoft/fast-element": "^2.10.4" } }, - "packages/fast-ssr": { - "name": "@microsoft/fast-ssr", - "version": "1.0.0-beta.40", - "deprecated": "This package is deprecated. Please use @microsoft/fast-build and @microsoft/webui instead.", - "license": "MIT", - "dependencies": { - "parse5": "^6.0.1", - "tslib": "^2.6.3" - }, - "devDependencies": { - "@microsoft/fast-element": "^2.10.4", - "@types/parse5": "^5.0.0" - }, - "peerDependencies": { - "@microsoft/fast-element": "^2.10.4" - } - }, "packages/fast-test-harness": { "name": "@microsoft/fast-test-harness", "version": "0.0.1", @@ -8769,7 +7024,7 @@ }, "peerDependencies": { "@microsoft/fast-build": ">=0.4.0 <1.0.0", - "@microsoft/fast-html": ">=1.0.0-alpha.49 <1.0.0", + "@microsoft/fast-html": ">=1.0.0-alpha.50 <1.0.0", "@playwright/test": ">=1.40.0", "vite": ">=7.0.0" }, @@ -8784,8 +7039,6 @@ }, "packages/fast-test-harness/node_modules/accepts": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", "dependencies": { "mime-types": "^3.0.0", @@ -8797,8 +7050,6 @@ }, "packages/fast-test-harness/node_modules/body-parser": { "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", @@ -8821,8 +7072,6 @@ }, "packages/fast-test-harness/node_modules/content-disposition": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz", - "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", "license": "MIT", "engines": { "node": ">=18" @@ -8834,8 +7083,6 @@ }, "packages/fast-test-harness/node_modules/cookie-signature": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", "engines": { "node": ">=6.6.0" @@ -8843,8 +7090,6 @@ }, "packages/fast-test-harness/node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -8860,8 +7105,6 @@ }, "packages/fast-test-harness/node_modules/express": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", "dependencies": { "accepts": "^2.0.0", @@ -8903,8 +7146,6 @@ }, "packages/fast-test-harness/node_modules/finalhandler": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -8924,8 +7165,6 @@ }, "packages/fast-test-harness/node_modules/fresh": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8933,8 +7172,6 @@ }, "packages/fast-test-harness/node_modules/iconv-lite": { "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -8949,8 +7186,6 @@ }, "packages/fast-test-harness/node_modules/media-typer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8958,8 +7193,6 @@ }, "packages/fast-test-harness/node_modules/merge-descriptors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", "engines": { "node": ">=18" @@ -8970,8 +7203,6 @@ }, "packages/fast-test-harness/node_modules/mime-db": { "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -8979,8 +7210,6 @@ }, "packages/fast-test-harness/node_modules/mime-types": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" @@ -8995,14 +7224,10 @@ }, "packages/fast-test-harness/node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "packages/fast-test-harness/node_modules/negotiator": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -9010,8 +7235,6 @@ }, "packages/fast-test-harness/node_modules/raw-body": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -9025,8 +7248,6 @@ }, "packages/fast-test-harness/node_modules/send": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "license": "MIT", "dependencies": { "debug": "^4.4.3", @@ -9051,8 +7272,6 @@ }, "packages/fast-test-harness/node_modules/serve-static": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", @@ -9070,8 +7289,6 @@ }, "packages/fast-test-harness/node_modules/type-is": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", "dependencies": { "content-type": "^1.0.5", @@ -9082,6 +7299,14 @@ "node": ">= 0.6" } }, + "sites/benchmarks": { + "name": "@microsoft/fast-bench", + "version": "0.0.0", + "dependencies": { + "@microsoft/fast-element": "*", + "@microsoft/fast-html": "*" + } + }, "sites/website": { "name": "@microsoft/fast-site", "version": "0.6.2", @@ -9114,8 +7339,6 @@ }, "sites/website/node_modules/@microsoft/api-extractor-model": { "version": "7.33.4", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.33.4.tgz", - "integrity": "sha512-u1LTaNTikZAQ9uK6KG1Ms7nvNedsnODnspq/gH2dcyETWvH4hVNGNDvRAEutH66kAmxA4/necElqGNs1FggC8w==", "license": "MIT", "dependencies": { "@microsoft/tsdoc": "~0.16.0", @@ -9125,8 +7348,6 @@ }, "sites/website/node_modules/@rushstack/node-core-library": { "version": "5.20.3", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.20.3.tgz", - "integrity": "sha512-95JgEPq2k7tHxhF9/OJnnyHDXfC9cLhhta0An/6MlkDsX2A6dTzDrTUG18vx4vjc280V0fi0xDH9iQczpSuWsw==", "license": "MIT", "dependencies": { "ajv": "~8.18.0", @@ -9149,8 +7370,6 @@ }, "sites/website/node_modules/@rushstack/terminal": { "version": "0.22.3", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.22.3.tgz", - "integrity": "sha512-gHC9pIMrUPzAbBiI4VZMU7Q+rsCzb8hJl36lFIulIzoceKotyKL3Rd76AZ2CryCTKEg+0bnTj406HE5YY5OQvw==", "license": "MIT", "dependencies": { "@rushstack/node-core-library": "5.20.3", @@ -9168,8 +7387,6 @@ }, "sites/website/node_modules/@rushstack/ts-command-line": { "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-5.3.3.tgz", - "integrity": "sha512-c+ltdcvC7ym+10lhwR/vWiOhsrm/bP3By2VsFcs5qTKv+6tTmxgbVrtJ5NdNjANiV5TcmOZgUN+5KYQ4llsvEw==", "license": "MIT", "dependencies": { "@rushstack/terminal": "0.22.3", diff --git a/package.json b/package.json index 80308cfcaee..4da620d6163 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,8 @@ "workspaces": [ "build", "packages/*", - "sites/website", - "examples/todo-app", - "examples/ssr" + "sites/*", + "examples/*" ], "engines": { "npm": ">=10.0.0", @@ -67,7 +66,6 @@ "lage": "2.15.8", "lefthook": "2.1.4", "rollup": "4.59.0", - "rollup-plugin-filesize": "10.0.0", "typescript": "5.3.3", "vite": "7.3.2", "yargs": "17.7.2" diff --git a/packages/README.md b/packages/README.md index ca567ec7cea..7ddcabf6eb2 100644 --- a/packages/README.md +++ b/packages/README.md @@ -9,13 +9,6 @@ Our web component packages. The `@microsoft/fast-element` library is a lightweight means to easily build performant, memory-efficient, standards-compliant Web Components. FAST Elements work in every major browser and can be used in combination with any front-end framework or even without a framework. To get up and running with `@microsoft/fast-element` see [the Getting Started guide](https://fast.design/docs/getting-started/quick-start). -## `@microsoft/fast-ssr` - -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![npm version](https://badge.fury.io/js/%40microsoft%2Ffast-ssr.svg)](https://badge.fury.io/js/%40microsoft%2Ffast-ssr) - -The `@microsoft/fast-ssr` package contains a NodeJS solution for rendering FAST templates and components. While primarily intended for supporting server-side rendering (SSR) scenarios, it also allows FAST to be used as a general purpose HTML templating solution. - ## `@microsoft/fast-router` [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) diff --git a/packages/bench/src/scenarios/attr-reflect/csr/main.ts b/packages/bench/src/scenarios/attr-reflect/csr/main.ts deleted file mode 100644 index 258bb980ded..00000000000 --- a/packages/bench/src/scenarios/attr-reflect/csr/main.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { html } from "@microsoft/fast-element"; -import { runBenchmark } from "../../harness.js"; -import { BenchElement } from "../element.js"; - -BenchElement.define({ - name: "bench-element", - template: html` - ${x => x.label} (${x => x.count}) - `, -}); - -let id = 0; - -runBenchmark(() => { - const count = ++id; - const el = document.createElement("bench-element") as BenchElement; - el.label = `item-${count}`; - el.count = count; - el.active = true; - return el; -}); diff --git a/packages/bench/src/scenarios/attr-reflect/element.ts b/packages/bench/src/scenarios/attr-reflect/element.ts deleted file mode 100644 index f2406393c26..00000000000 --- a/packages/bench/src/scenarios/attr-reflect/element.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { attr, FASTElement, nullableNumberConverter } from "@microsoft/fast-element"; - -export class BenchElement extends FASTElement { - @attr - label?: string; - - @attr({ converter: nullableNumberConverter }) - count?: number; - - @attr({ mode: "boolean" }) - active?: boolean; -} diff --git a/packages/bench/src/scenarios/basic/csr/main.ts b/packages/bench/src/scenarios/basic/csr/main.ts deleted file mode 100644 index 7c5ffc5af7f..00000000000 --- a/packages/bench/src/scenarios/basic/csr/main.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { html } from "@microsoft/fast-element"; -import { runBenchmark } from "../../harness.js"; -import { BenchElement } from "../element.js"; - -BenchElement.define({ - name: "bench-element", - template: html` - - `, -}); - -runBenchmark(() => { - const el = document.createElement("bench-element"); - el.innerHTML = "hello"; - return el; -}); diff --git a/packages/bench/src/scenarios/basic/element.ts b/packages/bench/src/scenarios/basic/element.ts deleted file mode 100644 index 1247ab9e4ba..00000000000 --- a/packages/bench/src/scenarios/basic/element.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { FASTElement } from "@microsoft/fast-element"; - -export class BenchElement extends FASTElement {} diff --git a/packages/bench/src/scenarios/bind-event/csr/main.ts b/packages/bench/src/scenarios/bind-event/csr/main.ts deleted file mode 100644 index 06d29b8d0f3..00000000000 --- a/packages/bench/src/scenarios/bind-event/csr/main.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { html } from "@microsoft/fast-element"; -import { runBenchmark } from "../../harness.js"; -import { BenchElement } from "../element.js"; - -BenchElement.define({ - name: "bench-element", - template: html` - - `, -}); - -runBenchmark(() => document.createElement("bench-element")); diff --git a/packages/bench/src/scenarios/bind-event/element.ts b/packages/bench/src/scenarios/bind-event/element.ts deleted file mode 100644 index 2cee5bcaf5b..00000000000 --- a/packages/bench/src/scenarios/bind-event/element.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { attr, FASTElement } from "@microsoft/fast-element"; - -export class BenchElement extends FASTElement { - @attr count: string = "0"; - - handleClick(): void { - this.count = String(parseInt(this.count, 10) + 1); - } -} diff --git a/packages/bench/src/scenarios/ref-slotted/csr/main.ts b/packages/bench/src/scenarios/ref-slotted/csr/main.ts deleted file mode 100644 index 83ba22f5426..00000000000 --- a/packages/bench/src/scenarios/ref-slotted/csr/main.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { html, ref, slotted } from "@microsoft/fast-element"; -import { runBenchmark } from "../../harness.js"; -import { BenchElement } from "../element.js"; - -BenchElement.define({ - name: "bench-element", - template: html` -

Title

- - `, -}); - -runBenchmark(() => { - const el = document.createElement("bench-element") as BenchElement; - const child = document.createElement("span"); - child.textContent = "slotted content"; - el.appendChild(child); - return el; -}); diff --git a/packages/bench/src/scenarios/ref-slotted/element.ts b/packages/bench/src/scenarios/ref-slotted/element.ts deleted file mode 100644 index 3ada06f6730..00000000000 --- a/packages/bench/src/scenarios/ref-slotted/element.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { FASTElement } from "@microsoft/fast-element"; - -export class BenchElement extends FASTElement { - heading!: HTMLHeadingElement; - slottedItems!: Element[]; -} diff --git a/packages/bench/src/scenarios/repeat/csr/main.ts b/packages/bench/src/scenarios/repeat/csr/main.ts deleted file mode 100644 index 6483c5d3703..00000000000 --- a/packages/bench/src/scenarios/repeat/csr/main.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { html, repeat } from "@microsoft/fast-element"; -import { runBenchmark } from "../../harness.js"; -import { BenchElement } from "../element.js"; - -BenchElement.define({ - name: "bench-element", - template: html` -
    - ${repeat( - x => x.items, - html` -
  • ${x => x}
  • - ` - )} -
- `, -}); - -runBenchmark(() => document.createElement("bench-element"), 100); diff --git a/packages/bench/src/scenarios/repeat/element.ts b/packages/bench/src/scenarios/repeat/element.ts deleted file mode 100644 index 8c97a9966cb..00000000000 --- a/packages/bench/src/scenarios/repeat/element.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { FASTElement } from "@microsoft/fast-element"; - -const items = Array.from({ length: 20 }, (_, i) => `Item ${i}`); - -export class BenchElement extends FASTElement { - items = items; -} diff --git a/packages/bench/src/scenarios/when/csr/main.ts b/packages/bench/src/scenarios/when/csr/main.ts deleted file mode 100644 index 17ddb1b39b3..00000000000 --- a/packages/bench/src/scenarios/when/csr/main.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { html, when } from "@microsoft/fast-element"; -import { runBenchmark } from "../../harness.js"; -import { BenchElement } from "../element.js"; - -BenchElement.define({ - name: "bench-element", - template: html` - ${when( - x => x.show, - html` - Visible - ` - )} - ${when( - x => !x.show, - html` - Hidden - ` - )} - `, -}); - -runBenchmark(() => document.createElement("bench-element")); diff --git a/packages/bench/src/scenarios/when/element.ts b/packages/bench/src/scenarios/when/element.ts deleted file mode 100644 index f5d0f974d69..00000000000 --- a/packages/bench/src/scenarios/when/element.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { FASTElement, observable } from "@microsoft/fast-element"; - -export class BenchElement extends FASTElement { - @observable show = true; -} diff --git a/packages/bench/src/scenarios/when/hydration/main.ts b/packages/bench/src/scenarios/when/hydration/main.ts deleted file mode 100644 index 17cbaddee9f..00000000000 --- a/packages/bench/src/scenarios/when/hydration/main.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { RenderableFASTElement, TemplateElement } from "@microsoft/fast-html"; -import { signalDone } from "../../harness.js"; -import { BenchElement } from "../element.js"; - -RenderableFASTElement(BenchElement).defineAsync({ - name: "bench-element", - templateOptions: "defer-and-hydrate", -}); - -performance.mark("bench-start"); - -TemplateElement.config({ - hydrationComplete() { - performance.mark("bench-end"); - signalDone(); - }, -}).define({ name: "f-template" }); diff --git a/packages/fast-element/DESIGN.md b/packages/fast-element/DESIGN.md index e8195564d72..195629123c0 100644 --- a/packages/fast-element/DESIGN.md +++ b/packages/fast-element/DESIGN.md @@ -508,3 +508,9 @@ src/ | [ARCHITECTURE_UPDATES.md](./ARCHITECTURE_UPDATES.md) | Updates queue, attribute and observable change batching | | [src/templating/TEMPLATE-BINDINGS.md](./src/templating/TEMPLATE-BINDINGS.md) | Full template binding pipeline: authoring → compilation → binding → DOM updates | | [docs/fast-element-2-changes.md](./docs/fast-element-2-changes.md) | Breaking changes from v1 to v2 | + +--- + +## Bundle Size Reporting + +The build generates a `SIZES.md` file that records minified, gzip, and brotli sizes for the CDN rollup bundle and each individually tree-shaken export. Sizes are measured using `esbuild` for per-export bundles and from the Rollup minified output for the CDN rollup bundle. Compression sizes use Node.js `node:zlib`. The documentation site copies this file into the resources section during its prebuild step. diff --git a/packages/fast-element/README.md b/packages/fast-element/README.md index 9f41e02094b..e2247d21e5f 100644 --- a/packages/fast-element/README.md +++ b/packages/fast-element/README.md @@ -51,4 +51,8 @@ For simplicity, examples throughout the documentation will assume the library ha :::tip Looking for a quick guide on building components? Check out [our Cheat Sheet](../resources/cheat-sheet.md#building-components). -::: \ No newline at end of file +::: + +## Export Sizes + +Bundle sizes for each tree-shakeable export are tracked in [`SIZES.md`](./SIZES.md) and regenerated on every build. See the [Export Sizes](https://www.fast.design/docs/2.x/resources/export-sizes/) documentation page for the latest numbers. \ No newline at end of file diff --git a/packages/fast-element/SIZES.md b/packages/fast-element/SIZES.md new file mode 100644 index 00000000000..84b6e32715f --- /dev/null +++ b/packages/fast-element/SIZES.md @@ -0,0 +1,20 @@ +# Export Sizes + +Bundle sizes for `@microsoft/fast-element` exports. + +| Export | Minified | Gzip | Brotli | +|--------|----------|------|--------| +| CDN Rollup Bundle | 67.59 KB | 20.00 KB | 17.93 KB | +| FASTElement | 28.10 KB | 8.75 KB | 7.87 KB | +| Updates | 3.61 KB | 1.48 KB | 1.26 KB | +| Observable | 8.12 KB | 2.99 KB | 2.66 KB | +| observable | 8.16 KB | 3.00 KB | 2.68 KB | +| attr | 3.55 KB | 1.42 KB | 1.19 KB | +| children | 6.15 KB | 2.34 KB | 2.07 KB | +| css | 11.32 KB | 4.07 KB | 3.66 KB | +| ref | 5.12 KB | 2.02 KB | 1.76 KB | +| slotted | 5.94 KB | 2.28 KB | 2.00 KB | +| volatile | 8.22 KB | 3.02 KB | 2.69 KB | +| when | 2.33 KB | 956 B | 771 B | +| html | 28.16 KB | 9.27 KB | 8.33 KB | +| repeat | 31.91 KB | 10.17 KB | 9.15 KB | diff --git a/packages/fast-element/package.json b/packages/fast-element/package.json index a7f4b9874ef..3ac862c6cfa 100644 --- a/packages/fast-element/package.json +++ b/packages/fast-element/package.json @@ -106,8 +106,9 @@ "doc:ci": "api-extractor run", "doc:exports": "node ./scripts/run-api-extractor.js", "doc:exports:ci": "node ./scripts/run-api-extractor.js ci", - "build": "npm run build:tsc && npm run build:rollup && npm run doc && npm run doc:exports", + "build": "npm run build:tsc && npm run build:rollup && npm run build:sizes && npm run doc && npm run doc:exports", "build:rollup": "rollup -c", + "build:sizes": "node scripts/measure-sizes.js", "build:tsc": "tsc -p ./tsconfig.json", "dev": "tsc -p ./tsconfig.json -w", "prepublishOnly": "npm run clean && npm run build", diff --git a/packages/fast-element/rollup.config.js b/packages/fast-element/rollup.config.js index 8998cf2304c..f41a5a1a9b9 100644 --- a/packages/fast-element/rollup.config.js +++ b/packages/fast-element/rollup.config.js @@ -1,4 +1,3 @@ -import filesize from "rollup-plugin-filesize"; import terser from "@rollup/plugin-terser"; import typescript from "@rollup/plugin-typescript"; @@ -11,10 +10,6 @@ const plugins = [ }, exclude: ["**/*.bench.*", "**/*.spec.*"], }), - filesize({ - showMinifiedSize: false, - showBrotliSize: true, - }), ]; export default [ diff --git a/packages/fast-element/scripts/measure-sizes.js b/packages/fast-element/scripts/measure-sizes.js new file mode 100644 index 00000000000..df0147675cd --- /dev/null +++ b/packages/fast-element/scripts/measure-sizes.js @@ -0,0 +1,110 @@ +import { readFileSync, writeFileSync } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { brotliCompressSync, gzipSync } from "node:zlib"; +import { build } from "esbuild"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const packageRoot = path.resolve(__dirname, ".."); + +const namedExports = [ + "FASTElement", + "Updates", + "Observable", + "observable", + "attr", + "children", + "css", + "ref", + "slotted", + "volatile", + "when", + "html", + "repeat", +]; + +function formatBytes(bytes) { + if (bytes < 1024) return `${bytes} B`; + return `${(bytes / 1024).toFixed(2)} KB`; +} + +function measureBuffer(buffer) { + const gzip = gzipSync(buffer); + const brotli = brotliCompressSync(buffer); + return { + minified: buffer.length, + gzip: gzip.length, + brotli: brotli.length, + }; +} + +async function measureExport(exportName) { + const contents = `import { ${exportName} } from "@microsoft/fast-element";\nexport { ${exportName} };\n`; + + const result = await build({ + stdin: { + contents, + resolveDir: packageRoot, + loader: "ts", + }, + bundle: true, + minify: true, + format: "esm", + write: false, + treeShaking: true, + }); + + const code = Buffer.from(result.outputFiles[0].contents); + return measureBuffer(code); +} + +async function measureCore() { + const coreBundle = path.resolve(packageRoot, "dist/fast-element.min.js"); + const buffer = readFileSync(coreBundle); + return measureBuffer(buffer); +} + +async function main() { + const results = []; + + // Measure CDN rollup bundle + const core = await measureCore(); + results.push({ name: "CDN Rollup Bundle", ...core }); + + // Measure each named export in parallel + const exportResults = await Promise.all( + namedExports.map(async name => { + const sizes = await measureExport(name); + return { name, ...sizes }; + }), + ); + results.push(...exportResults); + + // Generate markdown table + const lines = [ + "# Export Sizes", + "", + "Bundle sizes for `@microsoft/fast-element` exports.", + "", + "| Export | Minified | Gzip | Brotli |", + "|--------|----------|------|--------|", + ]; + + for (const { name, minified, gzip, brotli } of results) { + lines.push( + `| ${name} | ${formatBytes(minified)} | ${formatBytes(gzip)} | ${formatBytes(brotli)} |`, + ); + } + + lines.push(""); + + const outputPath = path.resolve(packageRoot, "SIZES.md"); + writeFileSync(outputPath, lines.join("\n")); + console.log(`Bundle sizes written to ${outputPath}`); +} + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/packages/fast-html/CHANGELOG.json b/packages/fast-html/CHANGELOG.json index b6ff6bcac02..01463b79363 100644 --- a/packages/fast-html/CHANGELOG.json +++ b/packages/fast-html/CHANGELOG.json @@ -1,6 +1,44 @@ { "name": "@microsoft/fast-html", "entries": [ + { + "date": "Wed, 22 Apr 2026 00:29:57 GMT", + "version": "1.0.0-alpha.50", + "tag": "@microsoft/fast-html_v1.0.0-alpha.50", + "comments": { + "prerelease": [ + { + "author": "7559015+janechu@users.noreply.github.com", + "package": "@microsoft/fast-html", + "commit": "0eb81e0d25fc8d42a032cdba9d6b3d7eac1b5dd2", + "comment": "feat: add properties path tree to ObserverMapConfig in fast-html" + } + ], + "none": [ + { + "author": "7559015+janechu@users.noreply.github.com", + "package": "@microsoft/fast-html", + "commit": "f28432a100e1ee2e2bcd0c6dcd6e61953f777854", + "comment": "chore: remove @microsoft/fast-ssr" + } + ] + } + }, + { + "date": "Tue, 21 Apr 2026 00:05:17 GMT", + "version": "1.0.0-alpha.49", + "tag": "@microsoft/fast-html_v1.0.0-alpha.49", + "comments": { + "none": [ + { + "author": "7559015+janechu@users.noreply.github.com", + "package": "@microsoft/fast-html", + "commit": "713e4f5274ce8561268e8348da21968be0350a99", + "comment": "chore: update webui to 0.0.10" + } + ] + } + }, { "date": "Sat, 18 Apr 2026 00:05:00 GMT", "version": "1.0.0-alpha.49", diff --git a/packages/fast-html/CHANGELOG.md b/packages/fast-html/CHANGELOG.md index 220569449ff..686f6fd54b6 100644 --- a/packages/fast-html/CHANGELOG.md +++ b/packages/fast-html/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @microsoft/fast-html - + +## 1.0.0-alpha.50 + +Wed, 22 Apr 2026 00:29:57 GMT + +### Changes + +- feat: add properties path tree to ObserverMapConfig in fast-html (7559015+janechu@users.noreply.github.com) + ## 1.0.0-alpha.49 Fri, 17 Apr 2026 00:26:37 GMT diff --git a/packages/fast-html/DESIGN.md b/packages/fast-html/DESIGN.md index fdf8d8312c9..7aeef6683aa 100644 --- a/packages/fast-html/DESIGN.md +++ b/packages/fast-html/DESIGN.md @@ -87,7 +87,43 @@ An optional layer that uses the `Schema` to automatically: - Install property-change handlers that wrap newly assigned objects/arrays in `Proxy` instances. - Propagate deep property mutations back through FAST's observable system so bindings re-render. -Enabled via `TemplateElement.options({ "my-element": { observerMap: "all" } })` or by passing a configuration object `TemplateElement.options({ "my-element": { observerMap: {} } })`. Both forms are equivalent; no configuration keys are defined at this time. +Enabled via `TemplateElement.options({ "my-element": { observerMap: "all" } })` or by passing a configuration object `TemplateElement.options({ "my-element": { observerMap: {} } })`. Both forms are equivalent and observe all root properties. + +#### Path-level observation control + +The `ObserverMapConfig` interface accepts an optional `properties` key that maps root property names to a recursive path tree controlling observation granularity: + +```typescript +TemplateElement.options({ + "my-element": { + observerMap: { + properties: { + user: { + name: true, // user.name — observed + details: { + age: true, // user.details.age — observed + history: false, // user.details.history — NOT observed + }, + }, + // root properties not listed here are skipped + }, + }, + }, +}); +``` + +Each path entry can be: +- **`true`** — observe this path and all descendants (unless overridden deeper). +- **`false`** — skip this path and all descendants (unless overridden deeper). +- **`ObserverMapPathNode`** — an object with an optional `$observe` boolean and child property overrides, allowing alternating opt-in/opt-out to arbitrary depth. + +When `properties` is omitted (`observerMap: {}` or `observerMap: "all"`), all root properties are observed. When `properties` is present but empty (`{ properties: {} }`), no root properties are observed. + +The resolution algorithm walks the schema and configuration tree in parallel: +1. If `properties` is present and a root property is not listed, it is skipped. +2. `true`/`false` booleans apply to the entire subtree. +3. `$observe` on a node object controls the current level; children inherit when unspecified. +4. Paths in the config but not in the schema are silently ignored (forward-compatible). ### `AttributeMap` — automatic `@attr` definitions @@ -152,6 +188,9 @@ import { RenderableFASTElement, TemplateElement, ObserverMap, + type ObserverMapConfig, + type ObserverMapPathEntry, + type ObserverMapPathNode, } from "@microsoft/fast-html"; ``` @@ -163,6 +202,14 @@ Three primary exports are intended for application code: | `RenderableFASTElement(Base)` | Mixin applied to your `FASTElement` subclass for hydration support. | | `ObserverMap` | Advanced: access the observer-map class directly if building tooling. | +Additionally, the following types are exported for use in `observerMap` configuration: + +| Type | Purpose | +|---|---| +| `ObserverMapConfig` | Configuration object for the `observerMap` option; accepts optional `properties` key. | +| `ObserverMapPathEntry` | `boolean \| ObserverMapPathNode` — a node in the observation path tree. | +| `ObserverMapPathNode` | Object node with optional `$observe` and child property overrides. | + --- ## Template Syntax @@ -204,7 +251,7 @@ flowchart TD G --> H[transformInnerHTML normalises HTML entities] H --> I["resolveStringsAndValues\nparses bindings and directives\nbuilds Schema, builds strings+values arrays"] I --> J{observerMap enabled?} - J -- yes --> K["ObserverMap.defineProperties\n→ Observable.defineProperty for each root prop\n→ install proxy change handlers"] + J -- yes --> K["ObserverMap.defineProperties\n→ applyConfigToSchema stamps $observe on schema nodes\n→ Observable.defineProperty for each root prop\n→ install proxy change handlers"] J -- no --> L K --> L["ViewTemplate.create strings,values\n→ registeredFastElement.template = viewTemplate"] L --> M["FASTElementDefinition.composeAsync\n→ element fully registered with platform"] @@ -290,13 +337,29 @@ flowchart LR B --> C[schema.addPath\ntype:'access'\npath:'user.details.age'\nrootProperty:'user'] C --> D["Schema.jsonSchemaMap\n{'my-el' => {'user' => JSONSchema}}"] D --> E[ObserverMap.defineProperties] - E --> F[Observable.defineProperty on prototype\nfor 'user'] - E --> G[install instanceResolverChanged handler] - G --> H[when user= is set:\nassignObservables → Proxy wraps user\ndeep mutations → Observable.notify] + E --> E1["applyConfigToSchema\nstamps $observe: false on excluded schema nodes"] + E1 --> F[Observable.defineProperty on prototype\nfor 'user'] + E1 --> G[install instanceResolverChanged handler] + G --> H["when user= is set:\nassignObservables checks schema.$observe\n→ Proxy wraps observed paths only\ndeep mutations → Observable.notify"] ``` For a deep dive into the schema structure, context tracking, and proxy system see [SCHEMA_OBSERVER_MAP.md](./SCHEMA_OBSERVER_MAP.md). +### `$observe` flag on schema nodes + +When an `ObserverMapConfig` with a `properties` key is provided, `ObserverMap.defineProperties()` calls `applyConfigToSchema()` to stamp `$observe: false` on excluded schema nodes **before** the proxy system runs. This is a one-time pre-processing pass that walks the config and schema trees in parallel: + +- `false` in the config → `$observe: false` is stamped recursively on the node and all its descendants. +- `$observe: false` on a config node → the schema node is stamped, and unlisted children inherit the stamp. +- `true` in the config → no stamp needed (observed is the default). +- Config paths not in the schema are silently ignored. + +**Convention: stamp-only-when-excluding.** The `$observe` flag is only ever set to `false` — it is never explicitly set to `true`. Absence of `$observe` (i.e. `undefined`) means the node is observed. This means: + +- When `observerMap: "all"` or `observerMap: {}` is used, `applyConfigToSchema` is never called and no schema nodes are mutated — zero overhead for the common case. +- The proxy system uses `isSchemaExcluded(schema)` (checks `$observe === false` with no observed descendants) as the single predicate for all skip/suppress decisions. +- Schema nodes without `$observe` are always treated as observed. + ### AttributeMap and leaf bindings When `attributeMap` is enabled (via `"all"`, `{}`, or a configuration object), `AttributeMap.defineProperties()` is called after parsing. It iterates `Schema.getRootProperties()` and skips any property whose schema entry contains `properties`, `type`, or `anyOf` — keeping only plain leaf bindings. For each leaf: diff --git a/packages/fast-html/README.md b/packages/fast-html/README.md index 58938468242..ba7c47f90b6 100644 --- a/packages/fast-html/README.md +++ b/packages/fast-html/README.md @@ -217,6 +217,53 @@ if (process.env.NODE_ENV === 'development') { } ``` +#### `observerMap` + +When `observerMap: "all"` (or `observerMap: {}`) is configured for an element, `@microsoft/fast-html` automatically sets up deep reactive observation for all root properties discovered in the template. Both `"all"` and `{}` are equivalent. + +For finer control, pass a configuration object with a `properties` key that maps root property names to a recursive path tree: + +```typescript +TemplateElement.options({ + "user-profile": { + observerMap: { + properties: { + user: { + name: true, // user.name — observed + details: { + age: true, // user.details.age — observed + history: false, // user.details.history — NOT observed + }, + }, + // root properties not listed here are skipped + }, + }, + }, +}).define({ name: "f-template" }); +``` + +Each path entry can be: +- **`true`** — observe this path and all descendants. +- **`false`** — skip this path and all descendants. +- **An object** with an optional `$observe` boolean and child property overrides. + +Use `$observe: false` on a node to skip it by default, then re-include specific children: + +```typescript +observerMap: { + properties: { + analytics: { + charts: { + $observe: false, // charts NOT observed by default + activeChart: true, // ...except activeChart IS observed + }, + }, + }, +} +``` + +When `properties` is omitted, all root properties are observed (backward compatible). When `properties` is present but empty (`{ properties: {} }`), no root properties are observed. + #### `attributeMap` When `attributeMap: "all"` (or `attributeMap: {}`) is configured for an element, `@microsoft/fast-html` automatically creates reactive `@attr` properties for every **leaf binding** in the template — simple expressions like `{{foo}}` or `id="{{foo-bar}}"` that have no nested properties. Both `"all"` and `{}` are equivalent and use the default `"none"` attribute name strategy. diff --git a/packages/fast-html/RENDERING.md b/packages/fast-html/RENDERING.md index 989ef37a44c..f184d802dd8 100644 --- a/packages/fast-html/RENDERING.md +++ b/packages/fast-html/RENDERING.md @@ -131,7 +131,7 @@ A content binding syntax can be broken into parts: - `fe-b` - declares this as a FASTElement Binding. - `start|end` - indicates the start or end of the binding. - `number` - the number in order in the template of bindings, these increment for every binding. -- `UUID` - a unique string identifying the binding. The examples shown here have been generated from a 10 character long string used in the [FAST SSR package](https://github.com/microsoft/fast/blob/main/packages/fast-ssr/src/template-parser/id-generator.ts). +- `UUID` - a unique string identifying the binding. - `fe-b` - closes the binding comment. Bindings use `$$` as a separator string between the parts. diff --git a/packages/fast-html/docs/api-report.api.md b/packages/fast-html/docs/api-report.api.md index c209b1bc085..4531dcaa3e2 100644 --- a/packages/fast-html/docs/api-report.api.md +++ b/packages/fast-html/docs/api-report.api.md @@ -17,13 +17,27 @@ export interface AttributeMapConfig { // @public export class ObserverMap { // Warning: (ae-forgotten-export) The symbol "Schema" needs to be exported by the entry point index.d.ts - constructor(classPrototype: any, schema: Schema); + constructor(classPrototype: any, schema: Schema, config?: ObserverMapConfig); // (undocumented) defineProperties(): void; } // @public export interface ObserverMapConfig { + properties?: { + [rootProperty: string]: ObserverMapPathEntry; + }; +} + +// @public +export type ObserverMapPathEntry = boolean | ObserverMapPathNode; + +// @public +export interface ObserverMapPathNode { + // (undocumented) + $observe?: boolean; + // (undocumented) + [propertyName: string]: ObserverMapPathEntry | undefined; } // @public diff --git a/packages/fast-html/package.json b/packages/fast-html/package.json index f6aeba4ecb6..c00dc6e6a42 100644 --- a/packages/fast-html/package.json +++ b/packages/fast-html/package.json @@ -1,6 +1,6 @@ { "name": "@microsoft/fast-html", - "version": "1.0.0-alpha.49", + "version": "1.0.0-alpha.50", "type": "module", "author": { "name": "Microsoft", @@ -66,7 +66,7 @@ "devDependencies": { "@microsoft/fast-build": "^0.4.0", "@microsoft/fast-element": "^2.10.4", - "@microsoft/webui": "0.0.9" + "@microsoft/webui": "0.0.10" }, "beachball": { "disallowedChangeTypes": [ diff --git a/packages/fast-html/src/components/index.ts b/packages/fast-html/src/components/index.ts index 25db3b7df49..0b65205d3e9 100644 --- a/packages/fast-html/src/components/index.ts +++ b/packages/fast-html/src/components/index.ts @@ -9,5 +9,7 @@ export { type HydrationLifecycleCallbacks, type ObserverMapConfig, ObserverMapOption, + type ObserverMapPathEntry, + type ObserverMapPathNode, TemplateElement, } from "./template.js"; diff --git a/packages/fast-html/src/components/observer-map.spec.ts b/packages/fast-html/src/components/observer-map.spec.ts index 456010d7167..6254e27d133 100644 --- a/packages/fast-html/src/components/observer-map.spec.ts +++ b/packages/fast-html/src/components/observer-map.spec.ts @@ -49,4 +49,142 @@ test.describe("ObserverMap", async () => { expect(instance.someData).not.toBe(nextValue); expect(instance.someData.$isProxy).toBeTruthy(); }); + + test.describe("properties config", () => { + test("should skip root properties not listed in config.properties", () => { + const testName = "test-skip-unlisted"; + const testSchema = new Schema(testName); + class SkipTest { + public included: any; + public excluded: any; + } + + const schemaMap = Schema.jsonSchemaMap.get(testName) as Map< + string, + JSONSchema + >; + schemaMap.set("included", { + $schema: "https://json-schema.org/draft/2019-09/schema", + $id: `https://fast.design/schemas/${testName}/included.json`, + type: "object", + properties: { val: { type: "string" } }, + [defsPropertyName]: {}, + }); + schemaMap.set("excluded", { + $schema: "https://json-schema.org/draft/2019-09/schema", + $id: `https://fast.design/schemas/${testName}/excluded.json`, + type: "object", + properties: { val: { type: "string" } }, + [defsPropertyName]: {}, + }); + + const om = new ObserverMap(SkipTest.prototype, testSchema, { + properties: { included: true }, + }); + om.defineProperties(); + + const instance = new SkipTest(); + instance.included = null; + instance.included = { val: "hello" }; + + // included should be proxied + expect(instance.included.$isProxy).toBeTruthy(); + + // excluded should remain a plain object + instance.excluded = { val: "world" }; + expect(instance.excluded.$isProxy).toBeUndefined(); + }); + + test("should skip root properties set to false", () => { + const testName = "test-skip-false"; + const testSchema = new Schema(testName); + class FalseTest { + public skipped: any; + } + + const schemaMap = Schema.jsonSchemaMap.get(testName) as Map< + string, + JSONSchema + >; + schemaMap.set("skipped", { + $schema: "https://json-schema.org/draft/2019-09/schema", + $id: `https://fast.design/schemas/${testName}/skipped.json`, + type: "object", + properties: { val: { type: "string" } }, + [defsPropertyName]: {}, + }); + + const om = new ObserverMap(FalseTest.prototype, testSchema, { + properties: { skipped: false }, + }); + om.defineProperties(); + + const instance = new FalseTest(); + instance.skipped = { val: "hello" }; + + // skipped should remain a plain object + expect(instance.skipped.$isProxy).toBeUndefined(); + }); + + test("should observe all properties when config has no properties key", () => { + const testName = "test-observe-all"; + const testSchema = new Schema(testName); + class AllTest { + public data: any; + } + + const schemaMap = Schema.jsonSchemaMap.get(testName) as Map< + string, + JSONSchema + >; + schemaMap.set("data", { + $schema: "https://json-schema.org/draft/2019-09/schema", + $id: `https://fast.design/schemas/${testName}/data.json`, + type: "object", + properties: { val: { type: "string" } }, + [defsPropertyName]: {}, + }); + + // Empty config object = observe all + const om = new ObserverMap(AllTest.prototype, testSchema, {}); + om.defineProperties(); + + const instance = new AllTest(); + instance.data = null; + instance.data = { val: "hello" }; + + expect(instance.data.$isProxy).toBeTruthy(); + }); + + test("should observe nothing when properties is empty", () => { + const testName = "test-observe-nothing"; + const testSchema = new Schema(testName); + class NoneTest { + public data: any; + } + + const schemaMap = Schema.jsonSchemaMap.get(testName) as Map< + string, + JSONSchema + >; + schemaMap.set("data", { + $schema: "https://json-schema.org/draft/2019-09/schema", + $id: `https://fast.design/schemas/${testName}/data.json`, + type: "object", + properties: { val: { type: "string" } }, + [defsPropertyName]: {}, + }); + + // properties: {} = observe nothing + const om = new ObserverMap(NoneTest.prototype, testSchema, { + properties: {}, + }); + om.defineProperties(); + + const instance = new NoneTest(); + instance.data = { val: "hello" }; + + expect(instance.data.$isProxy).toBeUndefined(); + }); + }); }); diff --git a/packages/fast-html/src/components/observer-map.ts b/packages/fast-html/src/components/observer-map.ts index 40ab0766d1a..40e63eace54 100644 --- a/packages/fast-html/src/components/observer-map.ts +++ b/packages/fast-html/src/components/observer-map.ts @@ -1,6 +1,116 @@ import { Observable } from "@microsoft/fast-element/observable.js"; -import { assignObservables, deepMerge } from "./utilities.js"; import type { JSONSchema, Schema } from "./schema.js"; +import type { ObserverMapConfig, ObserverMapPathEntry } from "./template.js"; +import { assignObservables, deepMerge } from "./utilities.js"; + +/** + * Determines whether a config entry (or any of its descendants) enables observation. + * Used to decide whether a root property needs an observable accessor and change handler. + */ +function hasObservedPath(entry: ObserverMapPathEntry): boolean { + if (typeof entry === "boolean") { + return entry; + } + + // ObserverMapPathNode + if (entry.$observe === true) { + return true; + } + + for (const key of Object.keys(entry)) { + if (key === "$observe") { + continue; + } + + const child = entry[key]; + + if (child !== undefined && hasObservedPath(child)) { + return true; + } + } + + // A node with no explicit $observe and no observed children: + // at the root level the default $observe is true, so a node like `{ }` (no children) + // is observed. But a node with `$observe: false` and no observed children is not. + return entry.$observe !== false; +} + +/** + * Stamps `$observe` flags onto schema nodes based on the config tree. + * After this one-time pass the proxy system can check `schema.$observe` + * instead of needing a separate config parameter threaded through every call. + * + * @param schema - A schema node (must have `properties` to recurse) + * @param entry - The corresponding config path entry + * @param inherited - The inherited `$observe` value from the parent + */ +function applyConfigToSchema( + schema: any, + entry: ObserverMapPathEntry, + inherited: boolean = true, +): void { + if (entry === false) { + stampObserveFalse(schema); + return; + } + + if (entry === true) { + // Explicitly observed — no stamp needed (default is observed) + return; + } + + // ObserverMapPathNode + const nodeObserve = entry.$observe ?? inherited; + + if (!nodeObserve) { + schema.$observe = false; + } + + if (!schema?.properties) { + return; + } + + for (const key of Object.keys(entry)) { + if (key === "$observe") { + continue; + } + + const childEntry = entry[key]; + const childSchema = schema.properties[key]; + + // Paths in config but not in schema are silently ignored + if (childEntry !== undefined && childSchema) { + applyConfigToSchema(childSchema, childEntry, nodeObserve); + } + } + + // For properties in the schema that are NOT listed in the config, + // they inherit the parent's $observe value + if (!nodeObserve) { + for (const key of Object.keys(schema.properties)) { + if (!(key in entry) && schema.properties[key]) { + stampObserveFalse(schema.properties[key]); + } + } + } +} + +/** + * Recursively stamps `$observe: false` on a schema node and all its descendants. + */ +function stampObserveFalse(schema: any): void { + if (!schema) { + return; + } + + schema.$observe = false; + + if (schema.properties) { + for (const key of Object.keys(schema.properties)) { + stampObserveFalse(schema.properties[key]); + } + } +} /** * ObserverMap provides functionality for caching binding paths, extracting root properties, @@ -9,17 +119,51 @@ import type { JSONSchema, Schema } from "./schema.js"; export class ObserverMap { private schema: Schema; private classPrototype: any; + private config: ObserverMapConfig | undefined; - constructor(classPrototype: any, schema: Schema) { + constructor(classPrototype: any, schema: Schema, config?: ObserverMapConfig) { this.classPrototype = classPrototype; this.schema = schema; + this.config = config; } public defineProperties(): void { const propertyNames = this.schema.getRootProperties(); const existingAccessors = Observable.getAccessors(this.classPrototype); + const configProperties = this.config?.properties; for (const propertyName of propertyNames) { + // When `properties` is present, skip root properties not listed in the config + if (configProperties && !(propertyName in configProperties)) { + continue; + } + + // Resolve the config entry for this root property + const configEntry: ObserverMapPathEntry | undefined = + configProperties?.[propertyName]; + + // Skip root properties explicitly set to `false` with no observed descendants + if (configEntry === false) { + continue; + } + + // Skip ObserverMapPathNode entries with no observed descendants + if ( + typeof configEntry === "object" && + configEntry !== null && + !hasObservedPath(configEntry) + ) { + continue; + } + + // Stamp $observe flags onto the schema so the proxy system + // can check schema nodes directly without a separate config tree + const rootSchema = this.schema.getSchema(propertyName); + + if (configEntry && rootSchema) { + applyConfigToSchema(rootSchema, configEntry); + } + // Skip if property already has an accessor (from `@attr` or `@observable` decorator) if (!existingAccessors.some(accessor => accessor.name === propertyName)) { Observable.defineProperty(this.classPrototype, propertyName); @@ -30,7 +174,7 @@ export class ObserverMap { this.classPrototype[changedMethodName] = this.defineChanged( propertyName, - existingChangedMethod + existingChangedMethod, ); } } @@ -40,13 +184,14 @@ export class ObserverMap { * @param target - The target instance that owns the root property * @param rootProperty - The name of the root property for notification purposes * @param object - The object to wrap with a proxy + * @param schema - The schema for the element * @returns A proxy that triggers notifications on property mutations */ private getAndAssignObservables( target: any, rootProperty: string, object: any, - schema: Schema + schema: Schema, ): typeof Proxy { let proxiedObject = object; @@ -55,7 +200,7 @@ export class ObserverMap { schema.getSchema(rootProperty) as JSONSchema, proxiedObject, target, - rootProperty + rootProperty, ); return proxiedObject; @@ -70,7 +215,7 @@ export class ObserverMap { */ private defineChanged = ( propertyName: string, - existingChangedMethod?: (prev: any, next: any) => void + existingChangedMethod?: (prev: any, next: any) => void, ): ((prev: any, next: any) => void) => { const getAndAssignObservablesAlias = this.getAndAssignObservables; const schema = this.schema; @@ -92,7 +237,7 @@ export class ObserverMap { this, propertyName, next, - schema + schema, ); } } else if (!isObjectAssignment) { diff --git a/packages/fast-html/src/components/schema.ts b/packages/fast-html/src/components/schema.ts index b546b83cc86..dd38de98d0b 100644 --- a/packages/fast-html/src/components/schema.ts +++ b/packages/fast-html/src/components/schema.ts @@ -14,6 +14,12 @@ interface JSONSchemaCommon { items?: any; anyOf?: Array; $ref?: string; + /** + * Stamped by `applyConfigToSchema` when an `ObserverMapConfig` excludes + * this path. When `false`, the proxy system skips observation for this + * node and (if all descendants are also `false`) its subtree. + */ + $observe?: boolean; } export interface JSONSchema extends JSONSchemaCommon { @@ -118,7 +124,7 @@ export class Schema { if (config.childrenMap) { childRef = this.getSchemaId( config.childrenMap.customElementName, - config.childrenMap.attributeName + config.childrenMap.attributeName, ); if (splitPath.length === 1) { @@ -137,7 +143,7 @@ export class Schema { schema, splitPath.slice(1), config.pathConfig.currentContext, - childRef + childRef, ); } else { if (!schema[defsPropertyName]?.[splitPath[0]]) { @@ -151,7 +157,7 @@ export class Schema { schema[defsPropertyName][splitPath[0]], splitPath.slice(1), config.pathConfig.currentContext as string, - childRef + childRef, ); } } @@ -163,7 +169,7 @@ export class Schema { schema, splitPath.at(-1) as string, // example items config.pathConfig.currentContext as string, // example item - config.pathConfig.parentContext + config.pathConfig.parentContext, ); if (splitPath.length > 2) { @@ -177,7 +183,7 @@ export class Schema { ], splitPath.slice(1, -1), config.pathConfig.parentContext, - childRef + childRef, ); } @@ -186,7 +192,7 @@ export class Schema { hasParentContext ? splitPath.slice(2) : splitPath.slice(1), config.pathConfig.currentContext, childRef, - "array" + "array", ); } else if (splitPath.length > 1) { let schemaDefinition; @@ -202,12 +208,12 @@ export class Schema { splitPath.slice(1), config.pathConfig.currentContext, childRef, - "array" + "array", ); } else { schema.type = "array"; schema[refPropertyName] = this.getDefsPath( - config.pathConfig.currentContext as string + config.pathConfig.currentContext as string, ); } @@ -281,7 +287,7 @@ export class Schema { $schema: "https://json-schema.org/draft/2019-09/schema", $id: this.getSchemaId(this.customElementName, propertyName), [defsPropertyName]: {}, - } + }, ); } @@ -295,7 +301,7 @@ export class Schema { schema: any, splitPath: string[], context: string, - childRef: string | null + childRef: string | null, ) { schema.type = "object"; @@ -312,7 +318,7 @@ export class Schema { schema.properties[splitPath[0]], splitPath.slice(1), context, - childRef + childRef, ); } else if (childRef) { if (schema.properties[splitPath[0]].anyOf) { @@ -337,7 +343,7 @@ export class Schema { splitPath: string[], context: string | null, childRef: string | null, - type: string = "object" + type: string = "object", ): any { schema.type = "object"; @@ -355,7 +361,7 @@ export class Schema { splitPath.slice(1), context, childRef, - type + type, ); } else if (type === "array") { if (splitPath.length > 1) { @@ -364,12 +370,12 @@ export class Schema { splitPath.slice(1), context, childRef, - type + type, ); } else { return this.addArrayToAnObject( schema.properties[splitPath[0]], - context as string + context as string, ); } } @@ -409,7 +415,7 @@ export class Schema { schema: any, propertyName: string, // e.g items currentContext: string, // e.g. item - parentContext: string | null + parentContext: string | null, ): void { if (schema[defsPropertyName][currentContext]) { return; @@ -431,7 +437,7 @@ export class Schema { private getParentContexts( schema: JSONSchema, parentContext: string | null, - contexts: Array = [] + contexts: Array = [], ): Array { if (parentContext === null) { return [null, ...contexts]; @@ -444,7 +450,7 @@ export class Schema { return this.getParentContexts( schema, parentParentContext.at(-1) as string | null, - [parentContext, ...contexts] + [parentContext, ...contexts], ); } } diff --git a/packages/fast-html/src/components/template.ts b/packages/fast-html/src/components/template.ts index da22428e669..3811e611cbb 100644 --- a/packages/fast-html/src/components/template.ts +++ b/packages/fast-html/src/components/template.ts @@ -51,12 +51,47 @@ export const ObserverMapOption = { all: "all", } as const; +/** + * A node in the observer-map path tree. + * + * - `true` → observe this path and all descendants (unless overridden by children). + * - `false` → do NOT observe this path or its descendants (unless overridden by children). + * - `ObserverMapPathNode` → configure child paths individually; + * the node itself is observed if `$observe` is true (default when parent is observed). + */ +export type ObserverMapPathEntry = boolean | ObserverMapPathNode; + +/** + * A node object in the observer-map path tree. + * + * `$observe` controls whether this node itself is observed. + * When omitted the value is inherited from the nearest ancestor + * that explicitly sets `$observe`. At the root level the default is `true`. + * + * Child property overrides are keyed by property name. + */ +export interface ObserverMapPathNode { + $observe?: boolean; + [propertyName: string]: ObserverMapPathEntry | undefined; +} + /** * Configuration object for the observerMap element option. - * No configuration keys are defined at this time; passing an empty - * object (`{}`) is equivalent to `"all"`. + * When `properties` is omitted (i.e. `observerMap: {}`), behaves like `"all"` — + * every root property is observed. When `properties` is present, only listed + * root properties participate in observer-map observation. */ -export interface ObserverMapConfig {} +export interface ObserverMapConfig { + /** + * Per-root-property observation control. + * Keys are root property names discovered in the template schema. + * Only root properties listed here participate in observer-map observation. + * Omitting this field is equivalent to `"all"`. + */ + properties?: { + [rootProperty: string]: ObserverMapPathEntry; + }; +} /** * Type for the observerMap element option. @@ -275,9 +310,17 @@ class TemplateElement extends FASTElement { } if (isMapOptionEnabled(TemplateElement.elementOptions[name]?.observerMap)) { + const observerMapOption = + TemplateElement.elementOptions[name]?.observerMap; + const observerMapConfig = + typeof observerMapOption === "object" && observerMapOption !== null + ? observerMapOption + : undefined; + this.observerMap = new ObserverMap( value.prototype, this.schema as Schema, + observerMapConfig, ); } diff --git a/packages/fast-html/src/components/utilities.ts b/packages/fast-html/src/components/utilities.ts index 07677a757bf..cd49d159af4 100644 --- a/packages/fast-html/src/components/utilities.ts +++ b/packages/fast-html/src/components/utilities.ts @@ -1177,11 +1177,40 @@ function getSchemaProperties(schema: any): any | null { return null; } +/** + * Checks whether a schema node (or any of its descendants) has observation enabled. + * Returns false only when the node and ALL its descendants are stamped with `$observe: false`. + */ +function hasObservedSchemaDescendant(schema: any): boolean { + if (schema?.$observe !== false) { + return true; + } + + const props = getSchemaProperties(schema); + + if (!props) { + return false; + } + + return Object.keys(props).some(k => hasObservedSchemaDescendant(props[k])); +} + +/** + * Checks whether a schema node is fully excluded from observation. + * A node is excluded when it is stamped `$observe: false` AND none of + * its descendants are observed (no re-included leaves beneath it). + */ +function isSchemaExcluded(schema: any): boolean { + return schema?.$observe === false && !hasObservedSchemaDescendant(schema); +} + /** * Assigns Observable properties to items in an array and sets up change notifications * @param proxiedData - The array data to make observable * @param schema - The schema defining the structure of array items * @param rootSchema - The root schema for the entire data structure + * @param target - The target element + * @param rootProperty - The root property name * @returns The array with observable properties and change notifications */ function assignObservablesToArray( @@ -1421,6 +1450,13 @@ function assignProxyToItemsInArray( const schemaProperties = getSchemaProperties(schema); getObjectProperties(proxiableItem, schemaProperties).forEach(key => { + const childSchema = schemaProperties[key]; + + // Skip properties fully excluded from observation + if (isSchemaExcluded(childSchema)) { + return; + } + // Initialize the property as undefined if it doesn't exist if (!(key in originalItem)) { originalItem[key] = undefined; @@ -1482,6 +1518,13 @@ function assignProxyToItemsInObject( if (type === "object" && schemaProperties) { // navigate through all items in the object getObjectProperties(proxiedData, schemaProperties).forEach(property => { + const childSchema = schemaProperties[property]; + + // Skip properties fully excluded from observation + if (isSchemaExcluded(childSchema)) { + return; + } + proxiedData[property] = assignProxyToItemsInObject( target, rootProperty, @@ -1491,11 +1534,19 @@ function assignProxyToItemsInObject( ); }); - // assign a Proxy to the object - proxiedData = assignProxy(schema, rootSchema, target, rootProperty, proxiedData); + // Assign a Proxy unless this level is fully excluded from observation + if (!isSchemaExcluded(schema)) { + proxiedData = assignProxy( + schema, + rootSchema, + target, + rootProperty, + proxiedData, + ); - // Add this target to the object's target list - addTargetToObject(proxiedData, target, rootProperty); + // Add this target to the object's target list + addTargetToObject(proxiedData, target, rootProperty); + } } else if (type === "array") { const context = findDef((schema as JSONSchema).items); @@ -1585,6 +1636,8 @@ export function assignProxy( object: any, ): typeof Proxy { if (!object.$isProxy) { + const schemaProperties = getSchemaProperties(schema); + // Create a proxy for the object that triggers Observable.notify on mutations const proxy = new Proxy(object, { set: (obj: any, prop: string | symbol, value: any) => { @@ -1594,6 +1647,15 @@ export function assignProxy( return true; } + const propName = typeof prop === "string" ? prop : String(prop); + const childSchema = schemaProperties?.[propName]; + + // If the property is fully excluded, assign without proxying or notifying + if (isSchemaExcluded(childSchema)) { + obj[prop] = value; + return true; + } + obj[prop] = assignObservables( schema, rootSchema, @@ -1615,8 +1677,16 @@ export function assignProxy( }, deleteProperty: (obj: any, prop: string | symbol) => { if (prop in obj) { + const propName = typeof prop === "string" ? prop : String(prop); + const childSchema = schemaProperties?.[propName]; + delete obj[prop]; + // Only suppress notification if fully excluded + if (isSchemaExcluded(childSchema)) { + return true; + } + notifyObservables(proxy); return true; diff --git a/packages/fast-html/src/index.ts b/packages/fast-html/src/index.ts index 8a8f5883fe1..aeae13fa25e 100644 --- a/packages/fast-html/src/index.ts +++ b/packages/fast-html/src/index.ts @@ -7,6 +7,8 @@ export { type AttributeMapConfig, ObserverMap, type ObserverMapConfig, + type ObserverMapPathEntry, + type ObserverMapPathNode, RenderableFASTElement, TemplateElement, } from "./components/index.js"; diff --git a/packages/fast-html/test/fixtures/observer-map-properties/entry.html b/packages/fast-html/test/fixtures/observer-map-properties/entry.html new file mode 100644 index 00000000000..bcf07a1e05e --- /dev/null +++ b/packages/fast-html/test/fixtures/observer-map-properties/entry.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/packages/fast-html/test/fixtures/observer-map-properties/fast-build.config.json b/packages/fast-html/test/fixtures/observer-map-properties/fast-build.config.json new file mode 100644 index 00000000000..c291972cdad --- /dev/null +++ b/packages/fast-html/test/fixtures/observer-map-properties/fast-build.config.json @@ -0,0 +1,6 @@ +{ + "entry": "entry.html", + "state": "state.json", + "output": "index.html", + "templates": "templates.html" +} diff --git a/packages/fast-html/test/fixtures/observer-map-properties/index.html b/packages/fast-html/test/fixtures/observer-map-properties/index.html new file mode 100644 index 00000000000..208c83a6fd1 --- /dev/null +++ b/packages/fast-html/test/fixtures/observer-map-properties/index.html @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/fast-html/test/fixtures/observer-map-properties/main.ts b/packages/fast-html/test/fixtures/observer-map-properties/main.ts new file mode 100644 index 00000000000..79ebbfbba56 --- /dev/null +++ b/packages/fast-html/test/fixtures/observer-map-properties/main.ts @@ -0,0 +1,169 @@ +import { FASTElement } from "@microsoft/fast-element"; +import { TemplateElement } from "@microsoft/fast-html"; + +class SelectiveObsElement extends FASTElement { + public user = { + name: "Alice", + age: 28, + history: { + joined: "2020-01-01", + visits: 100, + }, + location: { + city: "New York", + country: "USA", + }, + }; + + public settings = { + theme: "dark", + language: "en", + }; + + public analytics = { + charts: { + activeChart: "line", + cachedData: "heavy-data", + }, + summary: "good", + }; + + public updateUserName = () => { + this.user.name = "Bob"; + }; + + public updateUserAge = () => { + this.user.age = 29; + }; + + public updateHistory = () => { + this.user.history.visits = 200; + }; + + public updateLocation = () => { + this.user.location.city = "London"; + }; + + public updateSettings = () => { + this.settings.theme = "light"; + }; + + public updateActiveChart = () => { + this.analytics.charts.activeChart = "bar"; + }; + + public updateCachedData = () => { + this.analytics.charts.cachedData = "updated-heavy-data"; + }; + + public updateSummary = () => { + this.analytics.summary = "excellent"; + }; +} + +SelectiveObsElement.defineAsync({ + name: "selective-obs-element", +}); + +class AllObsElement extends FASTElement { + public user = { + name: "Alice", + }; + + public settings = { + theme: "dark", + }; + + public updateUserName = () => { + this.user.name = "Bob"; + }; + + public updateSettings = () => { + this.settings.theme = "light"; + }; +} + +AllObsElement.defineAsync({ + name: "all-obs-element", +}); + +class EmptyPropsElement extends FASTElement { + public user = { + name: "Alice", + }; + + public settings = { + theme: "dark", + }; + + public updateUserName = () => { + this.user.name = "Bob"; + }; + + public updateSettings = () => { + this.settings.theme = "light"; + }; +} + +EmptyPropsElement.defineAsync({ + name: "empty-props-element", +}); + +class ArraySelectiveElement extends FASTElement { + public items: any[] = [ + { text: "item-1", meta: { count: 1 } }, + { text: "item-2", meta: { count: 2 } }, + ]; + + public updateItemText = () => { + this.items[0].text = "updated-item-1"; + }; + + public addItem = () => { + this.items.push({ text: "item-3", meta: { count: 3 } }); + }; +} + +ArraySelectiveElement.defineAsync({ + name: "array-selective-element", +}); + +TemplateElement.options({ + "selective-obs-element": { + observerMap: { + properties: { + user: { + name: true, + age: true, + history: false, + location: true, + }, + // settings is NOT listed → skipped + analytics: { + charts: { + $observe: false, + activeChart: true, + }, + summary: true, + }, + }, + }, + }, + "all-obs-element": { + observerMap: {}, + }, + "empty-props-element": { + observerMap: { + properties: {}, + }, + }, + "array-selective-element": { + observerMap: { + properties: { + items: true, + }, + }, + }, +}).define({ + name: "f-template", +}); diff --git a/packages/fast-html/test/fixtures/observer-map-properties/observer-map-properties.spec.ts b/packages/fast-html/test/fixtures/observer-map-properties/observer-map-properties.spec.ts new file mode 100644 index 00000000000..36f2a1e9c2f --- /dev/null +++ b/packages/fast-html/test/fixtures/observer-map-properties/observer-map-properties.spec.ts @@ -0,0 +1,179 @@ +import { expect, test } from "@playwright/test"; + +test.describe("ObserverMap properties", async () => { + test.beforeEach(async ({ page }) => { + await page.goto("/fixtures/observer-map-properties/"); + await page.waitForSelector("selective-obs-element"); + }); + + test.describe("selective observation", () => { + test("should render initial values", async ({ page }) => { + const el = page.locator("selective-obs-element"); + + await expect(el.locator(".user-name")).toHaveText("Alice"); + await expect(el.locator(".user-age")).toHaveText("28"); + await expect(el.locator(".user-location-city")).toHaveText("New York"); + await expect(el.locator(".active-chart")).toHaveText("line"); + await expect(el.locator(".analytics-summary")).toHaveText("good"); + }); + + test("should update observed property: user.name", async ({ page }) => { + const el = page.locator("selective-obs-element"); + await el.locator("button:has-text('Update Name')").click(); + + await expect(el.locator(".user-name")).toHaveText("Bob"); + }); + + test("should update observed property: user.age", async ({ page }) => { + const el = page.locator("selective-obs-element"); + await el.locator("button:has-text('Update Age')").click(); + + await expect(el.locator(".user-age")).toHaveText("29"); + }); + + test("should NOT update excluded property: user.history (false)", async ({ + page, + }) => { + const el = page.locator("selective-obs-element"); + const initialValue = await el.locator(".user-history-visits").textContent(); + + await el.locator("button:has-text('Update History')").click(); + + // Wait a frame + await page.evaluate( + () => new Promise(resolve => requestAnimationFrame(() => resolve(true))), + ); + + // The text should NOT have updated because history is excluded + await expect(el.locator(".user-history-visits")).toHaveText(initialValue!); + }); + + test("should update observed property: user.location (true)", async ({ + page, + }) => { + const el = page.locator("selective-obs-element"); + await el.locator("button:has-text('Update Location')").click(); + + await expect(el.locator(".user-location-city")).toHaveText("London"); + }); + + test("should NOT update unlisted root property: settings", async ({ page }) => { + const el = page.locator("selective-obs-element"); + const initialValue = await el.locator(".settings-theme").textContent(); + + await el.locator("button:has-text('Update Settings')").click(); + + await page.evaluate( + () => new Promise(resolve => requestAnimationFrame(() => resolve(true))), + ); + + // settings is not listed in properties → skipped + await expect(el.locator(".settings-theme")).toHaveText(initialValue!); + }); + + test("should update observed property inside $observe:false branch: analytics.charts.activeChart", async ({ + page, + }) => { + const el = page.locator("selective-obs-element"); + await el.locator("button:has-text('Update Active Chart')").click(); + + await expect(el.locator(".active-chart")).toHaveText("bar"); + }); + + test("should NOT update excluded property: analytics.charts.cachedData (inherits $observe:false)", async ({ + page, + }) => { + const el = page.locator("selective-obs-element"); + const initialValue = await el.locator(".cached-data").textContent(); + + await el.locator("button:has-text('Update Cached Data')").click(); + + await page.evaluate( + () => new Promise(resolve => requestAnimationFrame(() => resolve(true))), + ); + + // cachedData inherits $observe:false from charts node + await expect(el.locator(".cached-data")).toHaveText(initialValue!); + }); + + test("should update observed property: analytics.summary (true)", async ({ + page, + }) => { + const el = page.locator("selective-obs-element"); + await el.locator("button:has-text('Update Summary')").click(); + + await expect(el.locator(".analytics-summary")).toHaveText("excellent"); + }); + }); + + test.describe("empty config object (observe all)", () => { + test("should update user.name with observerMap: {}", async ({ page }) => { + const el = page.locator("all-obs-element"); + await el.locator("button:has-text('Update Name')").click(); + + await expect(el.locator(".user-name")).toHaveText("Bob"); + }); + + test("should update settings.theme with observerMap: {}", async ({ page }) => { + const el = page.locator("all-obs-element"); + await el.locator("button:has-text('Update Settings')").click(); + + await expect(el.locator(".settings-theme")).toHaveText("light"); + }); + }); + + test.describe("empty properties object (observe nothing)", () => { + test("should NOT update user.name with properties: {}", async ({ page }) => { + const el = page.locator("empty-props-element"); + const initialValue = await el.locator(".user-name").textContent(); + + await el.locator("button:has-text('Update Name')").click(); + + await page.evaluate( + () => new Promise(resolve => requestAnimationFrame(() => resolve(true))), + ); + + await expect(el.locator(".user-name")).toHaveText(initialValue!); + }); + + test("should NOT update settings.theme with properties: {}", async ({ page }) => { + const el = page.locator("empty-props-element"); + const initialValue = await el.locator(".settings-theme").textContent(); + + await el.locator("button:has-text('Update Settings')").click(); + + await page.evaluate( + () => new Promise(resolve => requestAnimationFrame(() => resolve(true))), + ); + + await expect(el.locator(".settings-theme")).toHaveText(initialValue!); + }); + }); + + test.describe("array with selective observation", () => { + test("should render initial array items", async ({ page }) => { + const el = page.locator("array-selective-element"); + + await expect(el.locator(".item-text").first()).toHaveText("item-1"); + await expect(el.locator(".item-text").nth(1)).toHaveText("item-2"); + }); + + test("should update item text in observed array", async ({ page }) => { + const el = page.locator("array-selective-element"); + await el.locator("button:has-text('Update Item Text')").click(); + + await expect(el.locator(".item-text").first()).toHaveText("updated-item-1"); + }); + + test("should add items to observed array", async ({ page }) => { + const el = page.locator("array-selective-element"); + + await expect(el.locator(".item-row")).toHaveCount(2); + + await el.locator("button:has-text('Add Item')").click(); + + await expect(el.locator(".item-row")).toHaveCount(3); + await expect(el.locator(".item-text").nth(2)).toHaveText("item-3"); + }); + }); +}); diff --git a/packages/fast-html/test/fixtures/observer-map-properties/state.json b/packages/fast-html/test/fixtures/observer-map-properties/state.json new file mode 100644 index 00000000000..dc9e72829c2 --- /dev/null +++ b/packages/fast-html/test/fixtures/observer-map-properties/state.json @@ -0,0 +1,29 @@ +{ + "user": { + "name": "Alice", + "age": 28, + "history": { + "joined": "2020-01-01", + "visits": 100 + }, + "location": { + "city": "New York", + "country": "USA" + } + }, + "settings": { + "theme": "dark", + "language": "en" + }, + "analytics": { + "charts": { + "activeChart": "line", + "cachedData": "heavy-data" + }, + "summary": "good" + }, + "items": [ + { "text": "item-1", "meta": { "count": 1 } }, + { "text": "item-2", "meta": { "count": 2 } } + ] +} diff --git a/packages/fast-html/test/fixtures/observer-map-properties/templates.html b/packages/fast-html/test/fixtures/observer-map-properties/templates.html new file mode 100644 index 00000000000..7437ecf8063 --- /dev/null +++ b/packages/fast-html/test/fixtures/observer-map-properties/templates.html @@ -0,0 +1,55 @@ + + + + + + + + + + + + diff --git a/packages/fast-ssr/.npmignore b/packages/fast-ssr/.npmignore deleted file mode 100644 index f30392d5382..00000000000 --- a/packages/fast-ssr/.npmignore +++ /dev/null @@ -1,11 +0,0 @@ -test -test-utilities -server -temp -src -*.spec.js -api-extractor.json -.eslintrc.cjs -.prettierignore -playwright.config.cjs -tsconfig.json \ No newline at end of file diff --git a/packages/fast-ssr/ACKNOWLEDGEMENTS.md b/packages/fast-ssr/ACKNOWLEDGEMENTS.md deleted file mode 100644 index fac21d02af7..00000000000 --- a/packages/fast-ssr/ACKNOWLEDGEMENTS.md +++ /dev/null @@ -1,41 +0,0 @@ -# Acknowledgements -A big thank you to [Lit](https://github.com/lit) for their work on server-side rendering for Web Components. This package builds off the ideas and tentative community protocols proposed and implemented in [@lit-labs/ssr](https://github.com/lit/lit/tree/main/packages/labs/ssr), with the goal of aligning `@microsoft/fast-ssr` to these community protocols as they mature. - -Several modules have been copied with some modification from [@lit-labs/ssr](https://github.com/lit/lit/tree/main/packages/labs/ssr). Our hope is that as these protocols mature, these files can be removed and common resources leveraged instead. The following list of files have been copied / modified: -- [./src/element-renderer/element-renderer.ts]() -- [./src/template-parser/template-parser.ts]() -- [./src/escape-html.ts]() -- [./src/dom-shim.ts]() -- [./src/render-info.ts]() - -and written with the following [license](https://github.com/lit/lit/blob/main/packages/labs/ssr/LICENSE): - ---- -BSD 3-Clause License - -Copyright (c) 2019 Google LLC. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/packages/fast-ssr/CHANGELOG.json b/packages/fast-ssr/CHANGELOG.json deleted file mode 100644 index bb769463cc8..00000000000 --- a/packages/fast-ssr/CHANGELOG.json +++ /dev/null @@ -1,1476 +0,0 @@ -{ - "name": "@microsoft/fast-ssr", - "entries": [ - { - "date": "Tue, 14 Apr 2026 00:15:09 GMT", - "version": "1.0.0-beta.40", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.40", - "comments": { - "none": [ - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "e8ce63d65a17c94baf03f271b9fa269b7f27d3e1", - "comment": "Add test:chromium script for Chromium-only Playwright test runs" - } - ] - } - }, - { - "date": "Fri, 10 Apr 2026 00:21:15 GMT", - "version": "1.0.0-beta.40", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.40", - "comments": { - "prerelease": [ - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "84de68790134fe7a2050a9b75ba6d3ae877d64ed", - "comment": "chore: deprecate package in favor of @microsoft/fast-build and @microsoft/webui" - } - ] - } - }, - { - "date": "Tue, 07 Apr 2026 00:50:48 GMT", - "version": "1.0.0-beta.39", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.39", - "comments": { - "none": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "05ccb88f41eb44ec6cbe263335cc030de99f80a4", - "comment": "chore: add biome script to run biome on changed files in packages" - } - ] - } - }, - { - "date": "Thu, 26 Mar 2026 00:04:08 GMT", - "version": "1.0.0-beta.39", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.39", - "comments": { - "none": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "6b0fd6c4a4b0c635d4e5c18d251b28abbf32bab5", - "comment": "chore: migrate to biome for linting and formatting" - }, - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "ea46496f56cd94cb0dae65b7026998c88604aaac", - "comment": "chore: fix publish blocker due to biome" - } - ] - } - }, - { - "date": "Fri, 20 Mar 2026 00:07:36 GMT", - "version": "1.0.0-beta.39", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.39", - "comments": { - "none": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "99a38cb16397c299566bc6f10f910c9e4e3a6f44", - "comment": "chore: update tests to use Node.js" - }, - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "6df43be90d257a49389c188935400792b7108cc6", - "comment": "Split tests to assist in base PR build gate times" - }, - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "1dd81b899a21eb28ed7dd15bdf1c558196775c3e", - "comment": "chore: update dependencies and configurations" - } - ] - } - }, - { - "date": "Thu, 05 Mar 2026 00:09:03 GMT", - "version": "1.0.0-beta.39", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.39", - "comments": { - "prerelease": [ - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "d0aa03d8d69547d58626e1f859b8df6d4d981397", - "comment": "Tag SSR prerelease with latest" - } - ] - } - }, - { - "date": "Tue, 17 Feb 2026 20:49:30 GMT", - "version": "1.0.0-beta.38", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.38", - "comments": { - "none": [ - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "ee995d8eeddfed3085bc41494a34886d86116252", - "comment": "Remove foundation as a dependency" - } - ], - "prerelease": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "65f87c8f1fff03011d77f8159bae96e0f3fe9fce", - "comment": "chore: add @types/parse5 as a dev dependency" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.10.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Tue, 27 Jan 2026 17:28:54 GMT", - "version": "1.0.0-beta.37", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.37", - "comments": { - "prerelease": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "d1cd327a6d37cea742b1b1df48f807fe9a1da4f7", - "comment": "chore: hoist devDependencies" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.9.2", - "commit": "not available" - } - ] - } - }, - { - "date": "Tue, 16 Dec 2025 21:27:19 GMT", - "version": "1.0.0-beta.36", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.36", - "comments": { - "prerelease": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "2c8de46fbde0440593f559cd2ddd8d7c6248f68d", - "comment": "fix: correct hydration marker indexes for templates with host bindings" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.9.1", - "commit": "not available" - } - ] - } - }, - { - "date": "Mon, 08 Dec 2025 19:47:51 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.9.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Tue, 02 Dec 2025 21:47:00 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.8.5", - "commit": "not available" - } - ] - } - }, - { - "date": "Mon, 01 Dec 2025 18:46:00 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.8.4", - "commit": "not available" - } - ] - } - }, - { - "date": "Sun, 16 Nov 2025 07:14:25 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "13071055+chrisdholt@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "acbdd78666f70b0b49dc99f61b71af7c0b3e259e", - "comment": "chore: flatten repository package structure" - } - ] - } - }, - { - "date": "Wed, 12 Nov 2025 20:41:54 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.8.3", - "commit": "not available" - } - ] - } - }, - { - "date": "Fri, 31 Oct 2025 20:45:55 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "6fdf0254c94cb3caefe946803d0e393ab30c31f9", - "comment": "chore: hoist @playwright/test to root and upgrade to 1.56.1" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.8.2", - "commit": "not available" - } - ] - } - }, - { - "date": "Tue, 21 Oct 2025 16:17:27 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.8.1", - "commit": "not available" - } - ] - } - }, - { - "date": "Mon, 13 Oct 2025 00:37:08 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.8.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Wed, 20 Aug 2025 20:57:02 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.7.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Wed, 06 Aug 2025 07:15:14 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.6.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Wed, 16 Jul 2025 22:43:52 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.5.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Fri, 30 May 2025 05:02:03 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.4.1", - "commit": "not available" - } - ] - } - }, - { - "date": "Fri, 23 May 2025 23:52:29 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.4.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Mon, 05 May 2025 00:33:41 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.3.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Wed, 16 Apr 2025 15:53:12 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.2.1", - "commit": "not available" - } - ] - } - }, - { - "date": "Mon, 24 Mar 2025 18:26:13 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.2.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Thu, 13 Feb 2025 17:34:08 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "7bbe060abd0ca4b9f7bd7aba3937b604e476eaca", - "comment": "Specify prereleasePrefix, allow bumpDeps" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.1.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Wed, 11 Dec 2024 19:53:32 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "26c5078fff7b7d4990d4143913a71def113f2874", - "comment": "Update playwright image and dependency to latest" - }, - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "a3c98e184642949bbb5b4318b5e233b49ad0b902", - "comment": "Attempt to address flaky test by increasing timeout" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.1", - "commit": "not available" - } - ] - } - }, - { - "date": "Mon, 19 Aug 2024 22:04:19 GMT", - "version": "1.0.0-beta.35", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.35", - "comments": { - "none": [ - { - "author": "13071055+chrisdholt@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "630a5e25a953201afa016e54aa77cf68d9d7663a", - "comment": "update beachball and move disallowedChangeTypes to package.json" - }, - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "02762acdca5412565acb89fb5b985fb5453347e1", - "comment": "Fix a dependency issue with express open redirect vulnerability" - }, - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "78910b1158a6a24b717b3d94616fa93ab6786ab4", - "comment": "Remove yarn and lerna in favor of npm" - } - ], - "prerelease": [ - { - "author": "171390049+prabhujayapal@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "882eded0b9dbc7d129ae4e634878024a0d7ffc08", - "comment": "Adds support for FASTElement hydration" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0", - "commit": "not available" - } - ] - } - }, - { - "date": "Thu, 20 Jun 2024 17:00:56 GMT", - "version": "1.0.0-beta.33", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.33", - "comments": { - "prerelease": [ - { - "author": "seanmonahan@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "9a78d697ac6f9f799e420e48cf32ffec19800b9c", - "comment": "fix: typos in SSR README" - }, - { - "author": "seanmonahan@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "4a282aee05fadafb9f053e31cb9272517c272744", - "comment": "fix: change 'shadowroot' to 'shadowrootmode' to match spec" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.33", - "commit": "not available" - } - ], - "none": [ - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "4b23b5caa76c172d3ea6c6559699d632a278442c", - "comment": "tslib updated to fixed version" - }, - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "5dac26f674ca755476b5a38bda5506947b42de93", - "comment": "fix parse5 type imports" - }, - { - "author": "7559015+janechu@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "00bccd7812ca072fc2efdf39af7762bbfdc90846", - "comment": "Remove eslint config package" - }, - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "97ef4d7a3880212bbb4f895459a047429a113472", - "comment": "upgrade playwright to 1.41" - } - ] - } - }, - { - "date": "Wed, 20 Dec 2023 19:03:48 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.32", - "version": "1.0.0-beta.32", - "comments": { - "none": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "0eb5c61c4a92655d5aa44960c34474c9d4b95227", - "comment": "use local placeholder image in fast-ssr tests" - } - ], - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.32", - "commit": "fd65254531ac3a593b32528d81b44ebf82c8e4ab" - } - ] - } - }, - { - "date": "Fri, 18 Aug 2023 22:48:12 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.31", - "version": "1.0.0-beta.31", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.31", - "commit": "d4d8c961b3ad5262924120070057ad6554dfdcb9" - } - ] - } - }, - { - "date": "Fri, 18 Aug 2023 00:04:37 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.30", - "version": "1.0.0-beta.30", - "comments": { - "prerelease": [ - { - "author": "chhol@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "2dab94c0eda05bee7c4b497e68951d79d6fcbe46", - "comment": "Breaking: update fast-ssr export paths to include extensions" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.26", - "commit": "2dab94c0eda05bee7c4b497e68951d79d6fcbe46" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.30", - "commit": "2dab94c0eda05bee7c4b497e68951d79d6fcbe46" - } - ] - } - }, - { - "date": "Sat, 12 Aug 2023 00:26:36 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.29", - "version": "1.0.0-beta.29", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.25", - "commit": "2297004e14386b5a689ba96361f8d8eebee69cd8" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.29", - "commit": "2297004e14386b5a689ba96361f8d8eebee69cd8" - } - ] - } - }, - { - "date": "Fri, 16 Jun 2023 18:17:13 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.28", - "version": "1.0.0-beta.28", - "comments": { - "none": [ - { - "author": "chhol@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "ca0e62ee8d05f72d1d8c1ad66bd6eea8e3f0a4eb", - "comment": "update prettier and eslint-config-prettier versions" - } - ], - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.24", - "commit": "8250aa8352940584ff443b550ee756d49f01c478" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.28", - "commit": "8250aa8352940584ff443b550ee756d49f01c478" - } - ] - } - }, - { - "date": "Tue, 28 Mar 2023 22:14:10 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.27", - "version": "1.0.0-beta.27", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.23", - "commit": "032285c2bf0311f9f44cbc875b40696fc8f62857" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.27", - "commit": "032285c2bf0311f9f44cbc875b40696fc8f62857" - } - ] - } - }, - { - "date": "Sat, 11 Mar 2023 00:09:49 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.26", - "version": "1.0.0-beta.26", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.22", - "commit": "dcf64d0383f613fd0c79b6f4f5ef010fccdbc11f" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.26", - "commit": "dcf64d0383f613fd0c79b6f4f5ef010fccdbc11f" - } - ] - } - }, - { - "date": "Tue, 14 Feb 2023 04:02:36 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.25", - "version": "1.0.0-beta.25", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.21", - "commit": "e504d092f81623e6332fa8cdf72ce9114e6c842e" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.25", - "commit": "e504d092f81623e6332fa8cdf72ce9114e6c842e" - } - ] - } - }, - { - "date": "Wed, 11 Jan 2023 22:07:44 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.24", - "version": "1.0.0-beta.24", - "comments": { - "prerelease": [ - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "5c3b2f0431ae8f840d3dc778ff93be73b585c6e2", - "comment": "fix(fast-ssr): update to use html.partial" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.20", - "commit": "2bb85c931a84d4de3a8b61d6f26f89f2d9a525f6" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.24", - "commit": "2bb85c931a84d4de3a8b61d6f26f89f2d9a525f6" - } - ], - "none": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "555f1b2cd614a1d5a9bc3985fb892d040c110cb3", - "comment": "remove tooltip options from dom-shim spec" - } - ] - } - }, - { - "date": "Fri, 02 Dec 2022 01:18:22 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.23", - "version": "1.0.0-beta.23", - "comments": { - "prerelease": [ - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "22f68aaabe18d350ffb12469d53b09fec5be81d1", - "comment": "feat: shim DOMTokenList for class and part properties on HTMLElement" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.19", - "commit": "040867e9a2a9e0ae25b78dfb3265fbe8f60fe023" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.23", - "commit": "040867e9a2a9e0ae25b78dfb3265fbe8f60fe023" - } - ] - } - }, - { - "date": "Tue, 15 Nov 2022 02:40:34 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.22", - "version": "1.0.0-beta.22", - "comments": { - "prerelease": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "ebfe1a316b75ecdd52622d62a525b271626fb463", - "comment": "Added configuration option to fast-ssr to render custom directives" - }, - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "3c14603089495a7af8ed5b55122c418b47c45fd5", - "comment": "add new DOM Policy protection throughout" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.18", - "commit": "416dc9167e9d41e6ffe11d87ed79b2f455357923" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.22", - "commit": "416dc9167e9d41e6ffe11d87ed79b2f455357923" - } - ] - } - }, - { - "date": "Fri, 04 Nov 2022 22:28:49 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.21", - "version": "1.0.0-beta.21", - "comments": { - "prerelease": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "9b183666f84a94b40274391d016d3ceb00509d2c", - "comment": "export features from DOM shim, refactor for better TypeScript support" - }, - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "a5f67af6d27aa3bed5bffc10d0c58ebcc606a439", - "comment": "Adds export path for RequestStorage" - }, - { - "author": "daviwu@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "20f5c40d27283c4df856970e854c8712c85c29c1", - "comment": "Fix boolean attribute rendering issues and throw error for unknown/object type of attributes" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.21", - "commit": "e60decc0627e763249e74937e00fab61c5c748e6" - } - ] - } - }, - { - "date": "Tue, 01 Nov 2022 23:26:26 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.20", - "version": "1.0.0-beta.20", - "comments": { - "prerelease": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "32d18d0900047899d1dadfe94f7923b6164b0cf3", - "comment": "Adds `defer-hydration` attribute emission during rendering" - }, - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "b7bc2ba4dc3099ae1e33554c53e5675946302de9", - "comment": "Fixed bug preventing dist files from being included in the published package" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.17", - "commit": "32d18d0900047899d1dadfe94f7923b6164b0cf3" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.20", - "commit": "32d18d0900047899d1dadfe94f7923b6164b0cf3" - } - ] - } - }, - { - "date": "Fri, 28 Oct 2022 20:44:44 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.19", - "version": "1.0.0-beta.19", - "comments": { - "none": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "7aaf156483ac6f5922a529b5b54e04e87445d882", - "comment": "use floating-ui for menu-item submenus" - } - ], - "prerelease": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "2536c024febdf8a89300c257805a19a946f8039d", - "comment": "Adds shim for MediaQueryList.addEventListener and updates matchMedia to always use the window's MediaQueryList" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.16", - "commit": "5b745b1fb3bf249a7a2d172b7fb69cb08694aadd" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.19", - "commit": "5b745b1fb3bf249a7a2d172b7fb69cb08694aadd" - } - ] - } - }, - { - "date": "Tue, 25 Oct 2022 20:24:32 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.18", - "version": "1.0.0-beta.18", - "comments": { - "prerelease": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "a70a376f2f8ca6c162191dc1ba036ccd7b13cff0", - "comment": "add feature to disable rendering of a component by the element renderer" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.15", - "commit": "220cc7e0e0de490e51cc8b6f42ff46b03228beaa" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.18", - "commit": "220cc7e0e0de490e51cc8b6f42ff46b03228beaa" - } - ] - } - }, - { - "date": "Fri, 14 Oct 2022 18:26:11 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.17", - "version": "1.0.0-beta.17", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.14", - "commit": "bcfbcb5be4433fb1fb0fab1697f13d345980db87" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.17", - "commit": "bcfbcb5be4433fb1fb0fab1697f13d345980db87" - } - ] - } - }, - { - "date": "Mon, 10 Oct 2022 20:28:02 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.16", - "version": "1.0.0-beta.16", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.13", - "commit": "ed2977ef6556964e68ea3ab0e4951320a1527baf" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.16", - "commit": "ed2977ef6556964e68ea3ab0e4951320a1527baf" - } - ] - } - }, - { - "date": "Thu, 06 Oct 2022 23:21:20 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.15", - "version": "1.0.0-beta.15", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.12", - "commit": "a69c2e3c0700918fef5ba934909781cc8ab71384" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.15", - "commit": "a69c2e3c0700918fef5ba934909781cc8ab71384" - } - ] - } - }, - { - "date": "Wed, 05 Oct 2022 23:26:01 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.14", - "version": "1.0.0-beta.14", - "comments": { - "prerelease": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "e9d881182e7c5f8c5dd1cac2415599c38654c107", - "comment": "Added RequestStorageManager.uninstallDOMShim() method to support uninstalling installed DOM shims" - }, - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "21d1de94be2b9399ddc43a2b93c6483fa7304591", - "comment": "add {shadowOptions: null} support" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.11", - "commit": "21d1de94be2b9399ddc43a2b93c6483fa7304591" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.14", - "commit": "21d1de94be2b9399ddc43a2b93c6483fa7304591" - } - ] - } - }, - { - "date": "Mon, 03 Oct 2022 23:44:38 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.13", - "version": "1.0.0-beta.13", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.10", - "commit": "e23f4375f183f0672f9aeafd0e58411adb66ae90" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.13", - "commit": "e23f4375f183f0672f9aeafd0e58411adb66ae90" - } - ] - } - }, - { - "date": "Wed, 28 Sep 2022 20:45:51 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.12", - "version": "1.0.0-beta.12", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.9", - "commit": "08fab33015853b7f820fdfdac2aecddfeb31843f" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.12", - "commit": "08fab33015853b7f820fdfdac2aecddfeb31843f" - } - ] - } - }, - { - "date": "Tue, 27 Sep 2022 22:31:52 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.11", - "version": "1.0.0-beta.11", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.8", - "commit": "8834c6732c727d39f92f72b197388453a9c17f9b" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.11", - "commit": "8834c6732c727d39f92f72b197388453a9c17f9b" - } - ] - } - }, - { - "date": "Fri, 23 Sep 2022 22:53:27 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.10", - "version": "1.0.0-beta.10", - "comments": { - "none": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "d1918c1583855b1b4b1f368dee00c53f0cf900b3", - "comment": "updates README.md with docs for dom-shim augmentation." - } - ], - "prerelease": [ - { - "author": "863023+radium-v@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "ec2b158dcf39c8b4152b22c3b65963046b473e17", - "comment": "update playwright" - }, - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "c1909e9899d517f9483b24043d49a8b193af3c26", - "comment": "Refactor core components to support Promise return types" - }, - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "c1909e9899d517f9483b24043d49a8b193af3c26", - "comment": "Adds support for async component rendering through the PendingTask protocol" - }, - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "2edd63a8abe24c68cfc7c76d773c912c6f2d6543", - "comment": "fix: updae SSR to use the new behavior API" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.7", - "commit": "1646b26450a08a77c8bd6302560fe12cc6989ae1" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.10", - "commit": "1646b26450a08a77c8bd6302560fe12cc6989ae1" - } - ] - } - }, - { - "date": "Thu, 01 Sep 2022 21:53:34 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.9", - "version": "1.0.0-beta.9", - "comments": { - "prerelease": [ - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "95d7bd387e1cc78b3681e715298a1dfbd86ecefc", - "comment": "feat: expose backend of RequestStorageManager for advanced integration" - }, - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "675c4370613d49bb5a974bdfedb773b880a78b6e", - "comment": "add default renderInfo implementation to TemplateRenderer.render" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.6", - "commit": "6b0f08574475d8b28cc2df67bf72b9041c2ad285" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.9", - "commit": "6b0f08574475d8b28cc2df67bf72b9041c2ad285" - } - ] - } - }, - { - "date": "Fri, 26 Aug 2022 18:06:43 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.8", - "version": "1.0.0-beta.8", - "comments": { - "prerelease": [ - { - "author": "erhuan@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "4fe1bc5f1be71e2e0ea3bb46871c597fc993dc5f", - "comment": "After install DOM Shim, globals will now return the original global instead of the shimmed version in async local storage if code is not in storage scope." - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.8", - "commit": "4fe1bc5f1be71e2e0ea3bb46871c597fc993dc5f" - } - ] - } - }, - { - "date": "Thu, 18 Aug 2022 20:46:10 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.7", - "version": "1.0.0-beta.7", - "comments": { - "prerelease": [ - { - "author": "32497422+KingOfTac@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "29308db7920baaaac5b31b206d551669e165bc06", - "comment": "add subpath export for package.json to packages" - }, - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "d1492e8e378c30b684f4ff4bed5f86b99a88934f", - "comment": "implement CSSStyleSheet behavior to support DesignToken in SSR" - }, - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "e8fa95d3d2a219ce462cd4e70758b8f90083ee5a", - "comment": "feat: implement Declarative Shadow DOM polyfill as an optional plugin for FAST Server Side Rendering" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.5", - "commit": "0b57f1bc812e8e6371b7d27bb625f99a25bfaa66" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.7", - "commit": "0b57f1bc812e8e6371b7d27bb625f99a25bfaa66" - } - ] - } - }, - { - "date": "Wed, 27 Jul 2022 17:36:33 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.6", - "version": "1.0.0-beta.6", - "comments": { - "prerelease": [ - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.6", - "commit": "7df4548954621d6247ab7fe3fae1a1ba0d33294b" - } - ] - } - }, - { - "date": "Mon, 18 Jul 2022 21:10:01 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.5", - "version": "1.0.0-beta.5", - "comments": { - "prerelease": [ - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "27dc848327b25328e428f67505684d2171b58711", - "comment": "feat: update SSR to new binding APIs" - }, - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "a44a5497dd3210b5bc3ed0568f31505f9b93a312", - "comment": "feat: enable the render directive to work in SSR" - }, - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "4567188a47598b3d2589b05f039bea695f2b8875", - "comment": "fix: update server-side-rendering of the repeat directive to use the renamed dataBinding property of the repeat directive" - }, - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "7f4d6b5587f6eff52e5b7f414e27543bb4d7772d", - "comment": "feat: add request storage to support per-request context in server side rendering" - }, - { - "author": "roeisenb@microsoft.com", - "package": "@microsoft/fast-ssr", - "commit": "b32eb1004960da95b74dba7f111ee859b6655896", - "comment": "fix: server side rendering foundation tests" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.4", - "commit": "2ff46a32cdd9af12b236d0e2f3436a4de782e8ee" - }, - { - "author": "beachball", - "package": "@microsoft/fast-ssr", - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.5", - "commit": "2ff46a32cdd9af12b236d0e2f3436a4de782e8ee" - } - ], - "none": [ - { - "author": "nicholasrice@users.noreply.github.com", - "package": "@microsoft/fast-ssr", - "commit": "a27daf24a7117a6ccf1db673c1adfadff8548512", - "comment": "adds the render directive to the directive support table" - } - ] - } - }, - { - "date": "Wed, 22 Jun 2022 20:17:50 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.4", - "version": "1.0.0-beta.4", - "comments": { - "prerelease": [ - { - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.3", - "author": "nicholasrice@users.noreply.github.com", - "commit": "f28cdb9fdba9cb27904acfad7444de82d447f39e", - "package": "@microsoft/fast-ssr" - } - ] - } - }, - { - "date": "Wed, 15 Jun 2022 17:41:10 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.3", - "version": "1.0.0-beta.3", - "comments": { - "prerelease": [ - { - "comment": "Implemented Event support into SSR", - "author": "nicholasrice@users.noreply.github.com", - "commit": "d144322472e6ab439ed1e487eaeccd022d61ce19", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "feat: simplify execution context to align closer with v1", - "author": "roeisenb@microsoft.com", - "commit": "488d051999c43b93a0beef4db30a2bddd6bbdc64", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "chore: fix package.json type fields", - "author": "roeisenb@microsoft.com", - "commit": "e86a638b9e84cbf36d950025889742944e68e512", - "package": "@microsoft/fast-ssr" - } - ], - "none": [ - { - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.3", - "author": "7559015+janechu@users.noreply.github.com", - "commit": "a6b2a570c1cb592bc92b4c9d8366d197658819ae", - "package": "@microsoft/fast-ssr" - } - ] - } - }, - { - "date": "Wed, 01 Jun 2022 22:21:24 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.2", - "version": "1.0.0-beta.2", - "comments": { - "prerelease": [ - { - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.2", - "author": "nicholasrice@users.noreply.github.com", - "commit": "e4740b8f077b77954ae82ff698f144181e1504a7", - "package": "@microsoft/fast-ssr" - } - ] - } - }, - { - "date": "Wed, 01 Jun 2022 17:53:14 GMT", - "tag": "@microsoft/fast-ssr_v1.0.0-beta.1", - "version": "1.0.0-beta.1", - "comments": { - "prerelease": [ - { - "comment": "update npmignore file w/ new project structure", - "author": "nicholasrice@users.noreply.github.com", - "commit": "4699e77715068f8610aae908ede6356a249574b6", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "remove private field from package.json", - "author": "nicholasrice@users.noreply.github.com", - "commit": "4699e77715068f8610aae908ede6356a249574b6", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "chore: configure fast-ssr for internals stripping", - "author": "roeisenb@microsoft.com", - "commit": "4699e77715068f8610aae908ede6356a249574b6", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "Set prerelease version", - "author": "nicholasrice@users.noreply.github.com", - "commit": "5b313a3262b977acbee3c2efac87d0d14a82f792", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "Adds DOM shim support for APIs in @microsoft/fast-foundation", - "author": "nicholasrice@users.noreply.github.com", - "commit": "4699e77715068f8610aae908ede6356a249574b6", - "package": "@microsoft/fast-ssr" - } - ], - "none": [ - { - "comment": "update api extractor and typescript to use the latest versions", - "author": "chhol@microsoft.com", - "commit": "4699e77715068f8610aae908ede6356a249574b6", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "Bump @microsoft/fast-element to v2.0.0-beta.1", - "author": "roeisenb@microsoft.com", - "commit": "4699e77715068f8610aae908ede6356a249574b6", - "package": "@microsoft/fast-ssr" - }, - { - "comment": "Bump @microsoft/fast-foundation to v3.0.0-alpha.1", - "author": "roeisenb@microsoft.com", - "commit": "4699e77715068f8610aae908ede6356a249574b6", - "package": "@microsoft/fast-ssr" - } - ] - } - } - ] -} diff --git a/packages/fast-ssr/CHANGELOG.md b/packages/fast-ssr/CHANGELOG.md deleted file mode 100644 index ca479ac872f..00000000000 --- a/packages/fast-ssr/CHANGELOG.md +++ /dev/null @@ -1,381 +0,0 @@ -# Change Log - @microsoft/fast-ssr - - - - - -## 1.0.0-beta.40 - -Fri, 10 Apr 2026 00:21:15 GMT - -### Changes - -- chore: deprecate package in favor of @microsoft/fast-build and @microsoft/webui (7559015+janechu@users.noreply.github.com) - -## 1.0.0-beta.39 - -Thu, 05 Mar 2026 00:09:03 GMT - -### Changes - -- Tag SSR prerelease with latest (7559015+janechu@users.noreply.github.com) - -## 1.0.0-beta.38 - -Tue, 17 Feb 2026 20:49:30 GMT - -### Changes - -- chore: add @types/parse5 as a dev dependency (863023+radium-v@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.10.0 - -## 1.0.0-beta.37 - -Tue, 27 Jan 2026 17:28:54 GMT - -### Changes - -- chore: hoist devDependencies (863023+radium-v@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.9.2 - -## 1.0.0-beta.36 - -Tue, 16 Dec 2025 21:27:19 GMT - -### Changes - -- fix: correct hydration marker indexes for templates with host bindings (863023+radium-v@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.9.1 - -## 1.0.0-beta.35 - -Mon, 19 Aug 2024 22:04:19 GMT - -### Changes - -- Adds support for FASTElement hydration (171390049+prabhujayapal@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.0.0 - -## 1.0.0-beta.33 - -Thu, 20 Jun 2024 17:00:56 GMT - -### Changes - -- fix: typos in SSR README (seanmonahan@microsoft.com) -- fix: change 'shadowroot' to 'shadowrootmode' to match spec (seanmonahan@microsoft.com) -- Bump @microsoft/fast-foundation to v3.0.0-alpha.33 - -## 1.0.0-beta.32 - -Wed, 20 Dec 2023 19:03:48 GMT - -### Changes - -- Bump @microsoft/fast-foundation to v3.0.0-alpha.32 - -## 1.0.0-beta.31 - -Fri, 18 Aug 2023 22:48:12 GMT - -### Changes - -- Bump @microsoft/fast-foundation to v3.0.0-alpha.31 - -## 1.0.0-beta.30 - -Fri, 18 Aug 2023 00:04:37 GMT - -### Changes - -- Breaking: update fast-ssr export paths to include extensions (chhol@microsoft.com) -- Bump @microsoft/fast-element to v2.0.0-beta.26 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.30 - -## 1.0.0-beta.29 - -Sat, 12 Aug 2023 00:26:36 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.25 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.29 - -## 1.0.0-beta.28 - -Fri, 16 Jun 2023 18:17:13 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.24 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.28 - -## 1.0.0-beta.27 - -Tue, 28 Mar 2023 22:14:10 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.23 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.27 - -## 1.0.0-beta.26 - -Sat, 11 Mar 2023 00:09:49 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.22 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.26 - -## 1.0.0-beta.25 - -Tue, 14 Feb 2023 04:02:36 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.21 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.25 - -## 1.0.0-beta.24 - -Wed, 11 Jan 2023 22:07:44 GMT - -### Changes - -- fix(fast-ssr): update to use html.partial (roeisenb@microsoft.com) -- Bump @microsoft/fast-element to v2.0.0-beta.20 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.24 - -## 1.0.0-beta.23 - -Fri, 02 Dec 2022 01:18:22 GMT - -### Changes - -- feat: shim DOMTokenList for class and part properties on HTMLElement (roeisenb@microsoft.com) -- Bump @microsoft/fast-element to v2.0.0-beta.19 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.23 - -## 1.0.0-beta.22 - -Tue, 15 Nov 2022 02:40:34 GMT - -### Changes - -- Added configuration option to fast-ssr to render custom directives (nicholasrice@users.noreply.github.com) -- add new DOM Policy protection throughout (roeisenb@microsoft.com) -- Bump @microsoft/fast-element to v2.0.0-beta.18 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.22 - -## 1.0.0-beta.21 - -Fri, 04 Nov 2022 22:28:49 GMT - -### Changes - -- export features from DOM shim, refactor for better TypeScript support (nicholasrice@users.noreply.github.com) -- Adds export path for RequestStorage (nicholasrice@users.noreply.github.com) -- Fix boolean attribute rendering issues and throw error for unknown/object type of attributes (daviwu@microsoft.com) -- Bump @microsoft/fast-foundation to v3.0.0-alpha.21 - -## 1.0.0-beta.20 - -Tue, 01 Nov 2022 23:26:26 GMT - -### Changes - -- Adds `defer-hydration` attribute emission during rendering (nicholasrice@users.noreply.github.com) -- Fixed bug preventing dist files from being included in the published package (nicholasrice@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.0.0-beta.17 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.20 - -## 1.0.0-beta.19 - -Fri, 28 Oct 2022 20:44:44 GMT - -### Changes - -- Adds shim for MediaQueryList.addEventListener and updates matchMedia to always use the window's MediaQueryList (nicholasrice@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.0.0-beta.16 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.19 - -## 1.0.0-beta.18 - -Tue, 25 Oct 2022 20:24:32 GMT - -### Changes - -- add feature to disable rendering of a component by the element renderer (nicholasrice@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.0.0-beta.15 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.18 - -## 1.0.0-beta.17 - -Fri, 14 Oct 2022 18:26:11 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.14 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.17 - -## 1.0.0-beta.16 - -Mon, 10 Oct 2022 20:28:02 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.13 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.16 - -## 1.0.0-beta.15 - -Thu, 06 Oct 2022 23:21:20 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.12 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.15 - -## 1.0.0-beta.14 - -Wed, 05 Oct 2022 23:26:01 GMT - -### Changes - -- Added RequestStorageManager.uninstallDOMShim() method to support uninstalling installed DOM shims (nicholasrice@users.noreply.github.com) -- add {shadowOptions: null} support (nicholasrice@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.0.0-beta.11 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.14 - -## 1.0.0-beta.13 - -Mon, 03 Oct 2022 23:44:38 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.10 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.13 - -## 1.0.0-beta.12 - -Wed, 28 Sep 2022 20:45:51 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.9 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.12 - -## 1.0.0-beta.11 - -Tue, 27 Sep 2022 22:31:52 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.8 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.11 - -## 1.0.0-beta.10 - -Fri, 23 Sep 2022 22:53:27 GMT - -### Changes - -- update playwright (863023+radium-v@users.noreply.github.com) -- Refactor core components to support Promise return types (nicholasrice@users.noreply.github.com) -- Adds support for async component rendering through the PendingTask protocol (nicholasrice@users.noreply.github.com) -- fix: updae SSR to use the new behavior API (roeisenb@microsoft.com) -- Bump @microsoft/fast-element to v2.0.0-beta.7 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.10 - -## 1.0.0-beta.9 - -Thu, 01 Sep 2022 21:53:34 GMT - -### Changes - -- feat: expose backend of RequestStorageManager for advanced integration (roeisenb@microsoft.com) -- add default renderInfo implementation to TemplateRenderer.render (nicholasrice@users.noreply.github.com) -- Bump @microsoft/fast-element to v2.0.0-beta.6 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.9 - -## 1.0.0-beta.8 - -Fri, 26 Aug 2022 18:06:43 GMT - -### Changes - -- After install DOM Shim, globals will now return the original global instead of the shimmed version in async local storage if code is not in storage scope. (erhuan@microsoft.com) -- Bump @microsoft/fast-foundation to v3.0.0-alpha.8 - -## 1.0.0-beta.7 - -Thu, 18 Aug 2022 20:46:10 GMT - -### Changes - -- add subpath export for package.json to packages (32497422+KingOfTac@users.noreply.github.com) -- implement CSSStyleSheet behavior to support DesignToken in SSR (nicholasrice@users.noreply.github.com) -- feat: implement Declarative Shadow DOM polyfill as an optional plugin for FAST Server Side Rendering (roeisenb@microsoft.com) -- Bump @microsoft/fast-element to v2.0.0-beta.5 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.7 - -## 1.0.0-beta.6 - -Wed, 27 Jul 2022 17:36:33 GMT - -### Changes - -- Bump @microsoft/fast-foundation to v3.0.0-alpha.6 - -## 1.0.0-beta.5 - -Mon, 18 Jul 2022 21:10:01 GMT - -### Changes - -- feat: update SSR to new binding APIs (roeisenb@microsoft.com) -- feat: enable the render directive to work in SSR (roeisenb@microsoft.com) -- fix: update server-side-rendering of the repeat directive to use the renamed dataBinding property of the repeat directive (roeisenb@microsoft.com) -- feat: add request storage to support per-request context in server side rendering (roeisenb@microsoft.com) -- fix: server side rendering foundation tests (roeisenb@microsoft.com) -- Bump @microsoft/fast-element to v2.0.0-beta.4 -- Bump @microsoft/fast-foundation to v3.0.0-alpha.5 - -## 1.0.0-beta.4 - -Wed, 22 Jun 2022 20:17:50 GMT - -### Changes - -- Bump @microsoft/fast-element to v2.0.0-beta.3 (nicholasrice@users.noreply.github.com) - -## 1.0.0-beta.3 - -Wed, 15 Jun 2022 17:41:10 GMT - -### Changes - -- Implemented Event support into SSR (nicholasrice@users.noreply.github.com) -- feat: simplify execution context to align closer with v1 (roeisenb@microsoft.com) -- chore: fix package.json type fields (roeisenb@microsoft.com) - -## 1.0.0-beta.2 - -Wed, 01 Jun 2022 22:21:24 GMT - -### Changes - -- Bump @microsoft/fast-foundation to v3.0.0-alpha.2 (nicholasrice@users.noreply.github.com) - -## 1.0.0-beta.1 - -Wed, 01 Jun 2022 17:53:14 GMT - -### Changes - -- update npmignore file w/ new project structure (nicholasrice@users.noreply.github.com) -- remove private field from package.json (nicholasrice@users.noreply.github.com) -- chore: configure fast-ssr for internals stripping (roeisenb@microsoft.com) -- Set prerelease version (nicholasrice@users.noreply.github.com) -- Adds DOM shim support for APIs in @microsoft/fast-foundation (nicholasrice@users.noreply.github.com) diff --git a/packages/fast-ssr/README.md b/packages/fast-ssr/README.md deleted file mode 100644 index 00c586dfb66..00000000000 --- a/packages/fast-ssr/README.md +++ /dev/null @@ -1,374 +0,0 @@ -# FAST SSR - -> ⚠️ **Deprecated** -> -> `@microsoft/fast-ssr` is no longer actively maintained and has been deprecated in favor of [`@microsoft/fast-build`](https://www.npmjs.com/package/@microsoft/fast-build) and `@microsoft/webui`. -> Please migrate to those packages for server-side rendering support going forward. - -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -[![npm version](https://badge.fury.io/js/%40microsoft%2Ffast-ssr.svg)](https://badge.fury.io/js/%40microsoft%2Ffast-ssr) - -The `@microsoft/fast-ssr` package contains a NodeJS solution for rendering FAST templates and components. While primarily intended for supporting server-side rendering (SSR) scenarios, it also allows FAST to be used as a general purpose HTML templating solution. - -## Requirements -- [NodeJS ^16.0.0](https://nodejs.org) -- [`@microsoft/fast-element@^2.0.0`](https://www.npmjs.com/package/@microsoft/fast-element) - -## Important Notes -`@microsoft/fast-ssr` is built using ES modules. This documentation assumes all JavaScript is run as ES module scripts. If that is not the case in your project, you can force ES module format by converting `.js` extensions to `.mjs`. [Details on this here.](https://nodejs.org/api/packages.html) - -### Design Philosophy -Performance is a core tenant of this package. To help achieve that, it avoids needing a comprehensive DOM implementation to render components, instead relying on a minimal set of DOM globals provided by the packaged DOM shim. Doing so comes with an important idea to understand; non-custom elements (`
`, `

`, etc) are never instantiated as JavaScript objects and you cannot gain references to these elements declared in a template. The parts of a template containing these elements are emitted as-is to the SSR string result (with any bindings evaluated). It is for this reason [certain directives are no-ops](#directive-support-matrix). Additionally, components are rendered using only their template. Imperative code that adds elements or DOM content to a component will be invisible to the template renderer and will not be yielded in the final string result. - -## Community Alignment -`@microsoft/fast-ssr` internally implements the `ElementRenderer` interface proposed [here](https://github.com/webcomponents-cg/community-protocols/issues/7#issuecomment-825151215) and implemented in [`@lit-labs/ssr`](https://github.com/lit/lit/tree/main/packages/labs/ssr). The `ElementRenderer` interface allows Custom Elements created by different component authoring libraries to be rendered side-by-side, maximizing the portability and interoperability of Web Components. For more on how to do that, see the section on [configuring the RenderInfo object](#configuring-the-renderinfo-object). - -## Installation -Install `@microsoft/fast-ssr` and `@microsoft/fast-element` using your package manager of choice: - -```shell -npm install --save @microsoft/fast-ssr @microsoft/fast-element -``` -## Usage -### Installing the DOM Shim -`@microsoft/fast-ssr` requires a minimal DOM implementation to function. Install the shim by importing it. Doing so will ensure availability of certain DOM globals like `HTMLElement`, `Document`, etc. - -```js -import "@microsoft/fast-ssr/install-dom-shim.js"; -``` - -Alternatively, a full DOM implementation such as [`jsdom`](https://github.com/jsdom/jsdom) or [`happy-dom`](https://github.com/capricorn86/happy-dom) can be used. - -#### Augmenting the DOM Shim -To augment the properties installed by the DOM shim, import the Window factory and installer directly, and provide an object to `createWindow()` with the properties that should be added or overwritten. - -```ts -import { - createWindow, - installWindowOnGlobal, -} from '@microsoft/fast-ssr/dom-shim'; - -installWindowOnGlobal(createWindow({ isSSR: true })); -``` - -### Construct the Renderer -Import the renderer factory and construct a `TemplateRenderer`. -```js -import fastSSR from "@microsoft/fast-ssr"; - -const { templateRenderer } = fastSSR(); -``` - -### Define Custom Elements -Ensure that the custom elements used in the template you are rendering are defined in the `customElements` registry. This example defines a component directly, but you can also import any components being used: -```js -import { attr, customElement, html, FASTElement } from "@microsoft/fast-element"; - -@customElement({name: "my-element", template: html`

${x => x.message}

`}) -class MyElement extends FASTElement { - @attr - public message = "Hello World"; -} -``` - -### Rendering -With the `TemplateRenderer` created and a custom element defined, the `TemplateRenderer` can now render a template with that element. The result will be an `iterableIterator`, which allows the result to be streamed to the client before the entire template has been rendered. - -```js -const result = templateRenderer.render(html` - - - - - - -`); -``` - -The template being rendered can also be a fragment of HTML, it does not need to be a valid document: - -```js -const result = templateRenderer.render(html``); -``` - -#### Rendering Strings -The template renderer can also render `string` types just as it would a template: - -```js -const result = templateRenderer.render(""); -``` - -#### Rendering Templates with Bindings -A template can be rendered with arbitrary source data by providing that source as the third argument to `.render()`. When doing so, bindings are invoked with that source data: - -```ts -const result = templateRenderer.render(html` -

${x => x.message}

-`, templateRenderer.createRenderInfo(), { message: "hello world" }); -``` - -#### Rendering Templates with Directives -The `TemplateRenderer` can render templates with directives such as `when` and `repeat`. Some directives are no-ops, see the [directive support matrix](#directive-support-matrix) for details. - -```ts -import { when, repeat } from "@microsoft/fast-element"; - -const result = templateRenderer.render(html` - ${when(x => x.shouldRender, html` -

Colors of a pixel

- ${repeat(x => x.data, html`
  • ${color => color}
  • `)} - `)} -`, templateRenderer.createRenderInfo(), { shouldRender: true, data: ["red", "green", "blue"] }); -``` - -##### Directive Support Matrix - -|Directive Name|Support| -|-|-| -|[`children`](https://www.fast.design/docs/fast-element/using-directives#the-children-directive)|[![](https://img.shields.io/badge/-Unsupported-red)]()| -|[`ref`](https://www.fast.design/docs/fast-element/using-directives#the-ref-directive)|[![](https://img.shields.io/badge/-Unsupported-red)]()| -|`render`|[![](https://img.shields.io/badge/-Supported-brightgreen)]()| -|[`repeat`](https://www.fast.design/docs/fast-element/using-directives#the-repeat-directive)|[![](https://img.shields.io/badge/-Supported-brightgreen)]()| -|[`slotted`](https://www.fast.design/docs/fast-element/using-directives#the-slotted-directive)|[![](https://img.shields.io/badge/-Unsupported-red)]()| -|[`when`](https://www.fast.design/docs/fast-element/using-directives#the-when-directive)|[![](https://img.shields.io/badge/-Supported-brightgreen)]()| - -> Unsupported directives are no-ops. To understand more about why, see the [Design Philosophy.](#design-philosophy) - -##### Rendering Custom Directives -`@microsoft/fast-element` supports creating custom directives, and `@microsoft/fast-ssr` supports *rendering* -those custom directives by associating a SSR *renderer* to the custom directive. - -> This section does not cover *creating* a FAST directives - that documentation is coming to fast-element. - -With your directive (`MyDirective`) created, create a `ViewBehaviorFactoryRenderer` using the Directive - -```ts -const MyDirectiveRenderer: ViewBehaviorFactoryRenderer = { - // Instructs the TemplateRenderer to use this renderer when instances of - // 'MyDirective' are found in a template - matches: MyDirective, - *render(directive, renderInfo, source, templateRenderer, context) { - // Yield something, or do nothing - } -} -``` - -What a custom directive should *do* on the server depends highly on the scenario. As discussed above, several FAST directives are no-ops because the use-case doesn't make sense in an SSR context. The `render()` function is provided the directive instance, the SSR renderInfo object, any source data, the `TemplateRenderer`, and the `ExecutionContext` - use these to render what makes sense for the custom directive. - -To use the custom renderer, you must configure `fastSSR`: -```ts -import fastSSR from "@microsoft/fast-ssr"; - -const { templateRenderer} = fastSSR({viewBehaviorFactoryRenderers: [MyDirectiveRenderer]}); -``` - -Then, templates that use `MyDirective` can be rendered: - -```ts -templateRenderer.render(html`

    `); -``` -#### Rendering Asynchronous Components -Sometimes it is necessary for a component to do asynchronous work prior to rending it's template, and `@microsoft/fast-ssr` can be configured to support async work by supplying the `renderMode: "async"` configuration to the SSR factory: - -```ts -import fastSSR from "@microsoft/fast-ssr"; - -const { templateRenderer } = fastSSR({ - renderMode: "async" -}); -``` - -Communication that an element requires asynchronous rendering is facilitated by the [PendingTask](https://github.com/webcomponents-cg/community-protocols/blob/main/proposals/pending-task.md) community protocol. The component should emit a `PendingTaskEvent` during it's `connectedCallback()`. Doing so instructs the `TemplateRenderer` to resolve all pending tasks before continuing rendering: -```ts -import { PendingTaskEvent } from "@microsoft/fast-element/pending-task"; -// ... -class AsyncElement extends FASTElement { - async doWork() { - // ... - } - - connectedCallback() { - super.connectedCallback(); - - this.dispatchEvent(new PendingTaskEvent(this.doWork())); - } -} -``` - -When yielding the results of an async renderer, ensure that any `Promise` encountered is awaited: - -```ts - -for await (const part of templateRenderer.render(someAsyncTemplate)) { - res.write(part); -} -``` - -> It's important to note that to accurately render asynchronous components, template rendering must be effectively paused until async work is complete. This is inherently inefficient because that work gets initiated iteratively, during template rendering. If possible, it is best to architect your components and application in such a way that async work happens prior to template rendering, where initiation of async work can be better coordinated. - -#### Disabling Rendering for Specific Components -In cases where an author doesn't want a FAST component to render in SSR environments, but it is impractical to prevent *defining* that element in the custom element registry, the `ElementRenderer` exposes a mechanism to prevent matching elements it would otherwise match. Components can be disabled by tag-name (`"element-name"`), class constructor (`class MyElement extends FASTElement {}`), or `FASTElementDefinition` (`MyElement.compose({/* config */})`) - -```ts -// The element gets defined somewhere in an application -const name = "my-element"; -class MyElement extends FASTElement {} -const definition = MyElement.compose({name, template: html`

    Hello world

    `}); -definition.define(); - - -const { templateRenderer, ElementRenderer } = fastSSR(); -ElementRenderer.disable("my-element"); -// or -// ElementRenderer.disable(MyElement); -// or -// ElementRenderer.disable(definition); - -// Does not render template contents of the custom element -templateRenderer.render(html``); -``` - -### Hydration -#### `defer-hydration` Attribute -The `defer-hydration` attribute is an attribute that indicates to client-side code that the element should not hydrate it's view. When the attribute is removed, the element is free to hydrate itself. - -The SSR renderer can be configured to emit the `defer-hydration` attribute to all FAST custom elements: -```ts -const { templateRenderer } = fastSSR({deferHydration: true}); -``` - -> For more information on this community-protocol, see https://github.com/webcomponents-cg/community-protocols/pull/15 -#### Configuring FAST-Element -`@microsoft/fast-element` must be configured to respect the `defer-hydration` attribute. To do this, simply import the install code into the client-side application before defining the custom elements: -```ts -import "@microsoft/fast-element/install-element-hydration"; - -// Define custom elements -``` - -Alternatively, the `HydratableElementController` can be imported and installed manually: - -```ts -import { HydratableElementController } from "@microsoft/fast-element/element-hydration"; - -HydratableElementController.install(); -``` - -After you do this, `@microsoft/fast-element` will wait until the `defer-hydration` attribute is removed (if present during connection) before doing connection work like rendering templates, applying stylesheets, and binding behaviors. - -### Configuring the RenderInfo Object -`TemplateRenderer.render()` must be invoked with a `RenderInfo` object. Its purpose is to provide different element renderers to the process, as well as metadata about the rendering process. It can be used to render custom elements from different templating libraries in the same process. By default, `TemplateRenderer.render()` will create a `RenderInfo` object for you, but you can also easily construct your own using `TemplateRenderer.createRenderInfo()`: - -```js -const { templateRenderer, ElementRenderer } = fastSSR(); -templateRenderer.render(html``, templateRenderer.createRenderInfo()); -``` - -By default, `TemplateRenderer.createRenderInfo()` returns a `RenderInfo` object hydrated with only the `ElementRenderer` returned from `fastSSR()`. To configure this method to return a `RenderInfo` with *additional* or *different* elementRenderers, use the `TemplateRenderer.withDefaultElementRenderers()` method: - -```ts - import { AnotherElementRenderer } from "somewhere"; - const { templateRenderer, ElementRenderer } = fastSSR(); - - templateRenderer.withDefaultElementRenderers(ElementRenderer, AnotherElementRenderer); - - const renderInfo = templateRenderer.createRenderInfo(); - renderInfo.elementRenderers.includes(ElementRenderer); // true - renderInfo.elementRenderers.includes(AnotherElementRenderer); // true -``` - -To render elements built with another library, that library will need to provide an `ElementRenderer` for the library. For example, to render a Lit element along-side a FAST element, provide the FAST `ElementRenderer` *and* the Lit `ElementRenderer` to the `RenderInfo` object. There are two ways to accomplish this. First, the `templateRenderer` itself can be configured to always create `RenderInfo` objects using both renderers: - -```ts -import fastSSR from "@microsoft/fast-ssr"; -import { html } from "@microsoft/fast-element"; -import { LitElementRenderer } from "@lit-labs/ssr/lib/lit-element-renderer.js" - -const { templateRenderer, ElementRenderer } = fastSSR(); - -templateRenderer.withDefaultElementRenderers(ElementRenderer, LitElementRenderer); -// Some implementation that defines both FAST and Lit components -defineComponents(); - -const result = templateRenderer.render(html` - - -`); -``` - -Alternatively, a `RenderInfo` can be created with both renderers for only a single rendering process: -```ts -// ... -import fastSSR from "@microsoft/fast-ssr"; -import { html } from "@microsoft/fast-element"; -import { LitElementRenderer } from "@lit-labs/ssr/lib/lit-element-renderer.js" - -const { templateRenderer, ElementRenderer } = fastSSR(); - -// Some implementation that defines both FAST and Lit components -defineComponents(); - -const result = templateRenderer.render(html` - - -`, templateRenderer.createRenderInfo([ElementRenderer, LitElementRenderer])); -``` - - -### Scoping Requests - -The SSR renderer can be used in a variety of contexts, one of the most common being a web server. In the web server context, it's important to keep data scoped to the context of an individual request. The easiest way to do this is to use the W3C Context protocol to inject data and services into web components combined with FAST's `RequestStorage` mechanism. - -`RequestStorage` and `RequestStorageManager` provide a way to execute web server response handlers with per-request scoped Context. This can be set up for any web server framework, but FAST provides a simple helper for Express-compatible middleware. Here's a quick sample of how to configure middleware for per-request scoped DOM globals and Context. - -```ts -import fastSSR, { RequestStorageManager } from "@microsoft/fast-ssr"; -import express from "express"; - -const app = express(); -const port = 8080; -const { templateRenderer } = fastSSR(); - -defineWebComponents(); -const template = pageTemplate(); - -// set up per-request DOM globals and storage -app.use(RequestStorageManager.middleware()); - -app.get("/", (req, res) => { - // This is running in the scoped context. - // You can provide context instances here - // and they will be scoped to the request - // handler and cleaned up afterward. - - const stream = templateRenderer.render(template); - - for (const part of stream) { - res.write(part); - } - - res.end(); -}); - -app.listen(port, () => { - console.log(`Listening on port ${port}`); -}); -``` - -If working with a different framework not compatible with Express middleware, you can use the `RequestStorageManager` APIs to create custom middleware or set up individual requests. First, install the per-request DOM shim when setting up your web server: - -```ts -RequestStorageManager.installDOMShim(); -``` - -Then, at the beginning of each request or in your middleware, create the backing storage for the request: - -```ts -const storage = RequestStorageManager.createStorage(); -``` - -Finally, you must run the request handler function using the `RequestStorageManager` as follows: - -```ts -RequestStorageManager.run(storage, requestHandler); -``` \ No newline at end of file diff --git a/packages/fast-ssr/api-extractor.json b/packages/fast-ssr/api-extractor.json deleted file mode 100644 index ac17966c256..00000000000 --- a/packages/fast-ssr/api-extractor.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", - "extends": "../../api-extractor.json", - "mainEntryPointFilePath": "./dist/dts/exports.d.ts", - "dtsRollup": { - "enabled": true, - "untrimmedFilePath": "./dist/fast-ssr.untrimmed.d.ts", - "betaTrimmedFilePath": "./dist/fast-ssr.d.ts" - } -} \ No newline at end of file diff --git a/packages/fast-ssr/biome.json b/packages/fast-ssr/biome.json deleted file mode 100644 index b9e7bc794a5..00000000000 --- a/packages/fast-ssr/biome.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "root": false, - "extends": "//" -} diff --git a/packages/fast-ssr/docs/api-report.api.md b/packages/fast-ssr/docs/api-report.api.md deleted file mode 100644 index 5be286c839e..00000000000 --- a/packages/fast-ssr/docs/api-report.api.md +++ /dev/null @@ -1,196 +0,0 @@ -## API Report File for "@microsoft/fast-ssr" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -/// - -import { Aspected } from '@microsoft/fast-element'; -import { AsyncLocalStorage } from 'async_hooks'; -import { Constructable } from '@microsoft/fast-element'; -import { Disposable as Disposable_2 } from '@microsoft/fast-element'; -import { DOMContainer } from '@microsoft/fast-element/di.js'; -import { EventEmitter } from 'node:events'; -import { ExecutionContext } from '@microsoft/fast-element'; -import { FASTElement } from '@microsoft/fast-element'; -import { FASTElementDefinition } from '@microsoft/fast-element'; -import { HostController } from '@microsoft/fast-element'; -import { ViewBehaviorFactory } from '@microsoft/fast-element'; -import { ViewTemplate } from '@microsoft/fast-element'; - -// @beta (undocumented) -export interface AsyncElementRenderer extends Omit { - // (undocumented) - renderAttributes(): IterableIterator>; - // (undocumented) - renderShadow(renderInfo: RenderInfo): IterableIterator>; -} - -// @beta (undocumented) -export interface AsyncTemplateRenderer extends EventEmitter { - // (undocumented) - createRenderInfo(): RenderInfo; - // (undocumented) - readonly emitHydratableMarkup: boolean; - // (undocumented) - render(template: ViewTemplate | string, renderInfo?: RenderInfo, source?: unknown, context?: ExecutionContext): IterableIterator>; - // (undocumented) - withDefaultElementRenderers(...renderers: ConstructableElementRenderer[]): void; -} - -// @beta (undocumented) -export interface ConstructableElementRenderer { - // (undocumented) - new (tagName: string, renderInfo: RenderInfo): T; - // Warning: (ae-forgotten-export) The symbol "AttributesMap" needs to be exported by the entry point exports.d.ts - matchesClass(ctor: typeof HTMLElement, tagName: string, attributes: AttributesMap): boolean; -} - -// @beta (undocumented) -export interface ConstructableFASTElementRenderer extends ConstructableElementRenderer { - disable(...args: Array): void; -} - -// @beta -export const DeclarativeShadowDOMPolyfill: Readonly<{ - undefinedElementStyles: string; - nonStreamingTemplateUpgrade: string; -}>; - -// @beta (undocumented) -export interface ElementRenderer { - // (undocumented) - attributeChangedCallback(name: string, prev: string | null, next: string | null): void; - // (undocumented) - connectedCallback(): void; - // (undocumented) - disconnectedCallback(): void; - // (undocumented) - dispatchEvent(event: Event): boolean; - // (undocumented) - renderAttributes(): IterableIterator; - // (undocumented) - renderShadow(renderInfo: RenderInfo): IterableIterator; - // (undocumented) - setAttribute(name: string, value: string): void; - // (undocumented) - setProperty(name: string, value: unknown): void; - // (undocumented) - readonly tagName: string; -} - -// @beta (undocumented) -function fastSSR(): { - templateRenderer: TemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; - -// @beta (undocumented) -function fastSSR(config: Omit): { - templateRenderer: TemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; - -// @beta (undocumented) -function fastSSR(config: SSRConfiguration & Record<"renderMode", "sync">): { - templateRenderer: TemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; - -// @beta (undocumented) -function fastSSR(config: SSRConfiguration & Record<"renderMode", "async">): { - templateRenderer: AsyncTemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; -export default fastSSR; - -// @beta -export type Middleware = (req: any, res: any, next: () => any) => void; - -// @beta (undocumented) -export interface RenderInfo extends Disposable_2 { - // @deprecated - customElementHostStack: ElementRenderer[]; - customElementInstanceStack: ElementRenderer[]; - elementRenderers: ConstructableElementRenderer[]; - renderedCustomElementList: ElementRenderer[]; -} - -// @beta -export const RequestStorage: Readonly<{ - readonly container: DOMContainer; - set(key: any, value: any): any; - get: typeof getItem; - clear(): void; - delete(key: any): boolean; - has(key: any): boolean; -}>; - -// @beta -export const RequestStorageManager: Readonly<{ - backend: AsyncLocalStorage; - installDOMShim(): void; - uninstallDOMShim(): void; - installDIContextRequestStrategy(): void; - createStorage(options?: StorageOptions, req?: any): Map; - run(storage: Map, callback: () => T): T; - middleware(options?: StorageOptions): Middleware; -}>; - -// @beta -export interface SSRConfiguration { - deferHydration?: boolean | ((tagName: string) => boolean); - emitHydratableMarkup?: boolean; - renderMode?: "sync" | "async"; - styleRenderer?: StyleRenderer; - tryRecoverFromError?: boolean | ((e: unknown) => void); - viewBehaviorFactoryRenderers?: ViewBehaviorFactoryRenderer[]; -} - -// @beta -export type StorageOptions = { - createWindow?: (req: any) => { - [key: string]: unknown; - }; - storage?: Map; -}; - -// @beta -export interface StyleRenderer { - render(styles: Set): string; -} - -// Warning: (ae-forgotten-export) The symbol "TemplateCacheController" needs to be exported by the entry point exports.d.ts -// -// @public (undocumented) -export const templateCacheController: TemplateCacheController; - -// @beta (undocumented) -export interface TemplateRenderer extends EventEmitter { - // (undocumented) - createRenderInfo(): RenderInfo; - // (undocumented) - readonly emitHydratableMarkup: boolean; - // (undocumented) - render(template: ViewTemplate | string, renderInfo?: RenderInfo, source?: unknown, context?: ExecutionContext): IterableIterator; - // (undocumented) - withDefaultElementRenderers(...renderers: ConstructableElementRenderer[]): void; -} - -// @beta -export interface ViewBehaviorFactoryRenderer { - matcher: Constructable; - // Warning: (ae-forgotten-export) The symbol "DefaultTemplateRenderer" needs to be exported by the entry point exports.d.ts - render(behaviorFactory: T, renderInfo: RenderInfo, source: any, renderer: DefaultTemplateRenderer, context: ExecutionContext): IterableIterator; -} - -// Warnings were encountered during analysis: -// -// dist/dts/exports.d.ts:60:5 - (ae-forgotten-export) The symbol "SyncFASTElementRenderer" needs to be exported by the entry point exports.d.ts -// dist/dts/exports.d.ts:75:5 - (ae-forgotten-export) The symbol "AsyncFASTElementRenderer" needs to be exported by the entry point exports.d.ts -// dist/dts/request-storage.d.ts:33:5 - (ae-forgotten-export) The symbol "getItem" needs to be exported by the entry point exports.d.ts - -// (No @packageDocumentation comment for this package) - -``` diff --git a/packages/fast-ssr/package.json b/packages/fast-ssr/package.json deleted file mode 100644 index 5a2b717e9e3..00000000000 --- a/packages/fast-ssr/package.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "name": "@microsoft/fast-ssr", - "version": "1.0.0-beta.40", - "type": "module", - "author": { - "name": "Microsoft", - "url": "https://discord.gg/FcSNfg4" - }, - "homepage": "https://www.fast.design/", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/Microsoft/fast.git", - "directory": "packages/fast-ssr" - }, - "bugs": { - "url": "https://github.com/Microsoft/fast/issues/new/choose" - }, - "scripts": { - "clean": "tsc -b --clean src", - "build": "tsc -b src && npm run doc", - "doc": "api-extractor run --local", - "doc:ci": "api-extractor run", - "prepublishOnly": "npm run clean && npm run build", - "build-server": "tsc -b server", - "lint": "biome-changed", - "lint:fix": "biome-changed -- --fix", - "pretest": "npm run build-server && npm run build", - "test": "npm run test:node && npm run test:playwright", - "test:node": "node scripts/run-tests.mjs", - "test:playwright": "npm run pretest && playwright test", - "test:chromium": "npm run pretest && playwright test --project=chromium", - "test-server": "node server/dist/server.js" - }, - "deprecated": "This package is deprecated. Please use @microsoft/fast-build and @microsoft/webui instead.", - "description": "A package for rendering FAST Web Components outside the browser.", - "main": "dist/esm/exports.js", - "types": "dist/dts/exports.d.ts", - "exports": { - ".": { - "types": "./dist/dts/exports.d.ts", - "default": "./dist/esm/exports.js" - }, - "./install-dom-shim.js": "./dist/esm/install-dom-shim.js", - "./dom-shim": { - "types": "./dist/dts/dom-shim.d.ts", - "default": "./dist/esm/dom-shim.js" - }, - "./request-storage.js": { - "types": "./dist/dts/request-storage.d.ts", - "default": "./dist/esm/request-storage.js" - }, - "./package.json": "./package.json" - }, - "dependencies": { - "parse5": "^6.0.1", - "tslib": "^2.6.3" - }, - "peerDependencies": { - "@microsoft/fast-element": "^2.10.4" - }, - "devDependencies": { - "@types/parse5": "^5.0.0", - "@microsoft/fast-element": "^2.10.4" - }, - "beachball": { - "disallowedChangeTypes": [ - "major", - "minor", - "patch" - ], - "tag": "latest", - "prereleasePrefix": "beta" - } -} diff --git a/packages/fast-ssr/playwright.config.ts b/packages/fast-ssr/playwright.config.ts deleted file mode 100644 index 0d600049552..00000000000 --- a/packages/fast-ssr/playwright.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { defineConfig, devices } from "@playwright/test"; - -export default defineConfig({ - testDir: "./dist/esm", - testMatch: "**/*.pw.spec.js", - retries: 3, - projects: [ - { name: "chromium", use: { ...devices["Desktop Chrome"] } }, - { name: "firefox", use: { ...devices["Desktop Firefox"] } }, - { name: "webkit", use: { ...devices["Desktop Safari"] } }, - ], - webServer: { - command: "npm run test-server", - port: 8080, - timeout: 120 * 1000, - reuseExistingServer: false, - }, -}); diff --git a/packages/fast-ssr/scripts/run-tests.mjs b/packages/fast-ssr/scripts/run-tests.mjs deleted file mode 100644 index 12de7159510..00000000000 --- a/packages/fast-ssr/scripts/run-tests.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import { globSync } from "node:fs"; -import { execSync } from "node:child_process"; - -const files = globSync("dist/esm/**/*.spec.js", { - exclude: ["dist/esm/**/*.pw.spec.js"], -}); - -execSync(`node --test ${files.join(" ")}`, { stdio: "inherit" }); diff --git a/packages/fast-ssr/server/README.md b/packages/fast-ssr/server/README.md deleted file mode 100644 index c41dd618a80..00000000000 --- a/packages/fast-ssr/server/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Server -This project contains the web server that playwright tests are run against. To build, run `npm run build-server`. \ No newline at end of file diff --git a/packages/fast-ssr/server/placeholder.png b/packages/fast-ssr/server/placeholder.png deleted file mode 100644 index 300ae8d0766..00000000000 Binary files a/packages/fast-ssr/server/placeholder.png and /dev/null differ diff --git a/packages/fast-ssr/server/server.ts b/packages/fast-ssr/server/server.ts deleted file mode 100644 index 76b0e5e4a32..00000000000 --- a/packages/fast-ssr/server/server.ts +++ /dev/null @@ -1,89 +0,0 @@ -import fs from "fs"; -import path from "path"; -import { Readable } from "stream"; - -import express, { Request, Response } from "express"; - -const __dirname = path.resolve(path.dirname("")); -const PORT = 8080; -function handleRequest(req: Request, res: Response) { - res.set("Content-Type", "text/html"); - const stream = (Readable as any).from("hello world"); - stream.on("readable", function (this: any) { - let data: string; - - while ((data = this.read())) { - res.write(data); - } - }); - - stream.on("close", () => res.end()); - stream.on("error", (e: Error) => { - console.error(e); - process.exit(1); - }); -} - -function handlePathRequest( - mapPath: string, - contentType: string, - req: Request, - res: Response -) { - res.set("Content-Type", contentType); - fs.readFile(path.resolve(__dirname, mapPath), { encoding: "utf8" }, (err, data) => { - const stream = (Readable as any).from(data); - stream.on("readable", function (this: any) { - while ((data = this.read())) { - res.write(data); - } - }); - stream.on("close", () => res.end()); - stream.on("error", (e: Error) => { - console.error(e); - process.exit(1); - }); - }); -} - -const app = express(); -app.get("/", handleRequest); -app.get("/fast-style", (req: Request, res: Response) => - handlePathRequest("./src/styles/fast-style.fixture.html", "text/html", req, res) -); -app.get("/fast-style.js", (req: Request, res: Response) => - handlePathRequest( - "./dist/esm/styles/fast-style.js", - "application/javascript", - req, - res - ) -); -app.get("/fast-style-config.js", (req: Request, res: Response) => - handlePathRequest( - "./dist/esm/styles/fast-style-config.js", - "application/javascript", - req, - res - ) -); -app.get("/fast-command-buffer", (req: Request, res: Response) => - handlePathRequest( - "./src/fast-command-buffer/index.fixture.html", - "text/html", - req, - res - ) -); -app.get("/fast-command-buffer.js", (req: Request, res: Response) => - handlePathRequest( - "./dist/esm/fast-command-buffer/index.js", - "application/javascript", - req, - res - ) -); -app.get("/placeholder.png", (req, res) => - res.sendFile(path.resolve(__dirname, "./server/placeholder.png")) -); -app.listen(PORT); diff --git a/packages/fast-ssr/server/tsconfig.json b/packages/fast-ssr/server/tsconfig.json deleted file mode 100644 index fc7f3f2b6e1..00000000000 --- a/packages/fast-ssr/server/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../tsconfig.json", - "compilerOptions": { - "composite": true, - "rootDir": ".", - "outDir": "dist" - }, - "references": [{ "path": "../src"}] -} diff --git a/packages/fast-ssr/src/configure-fast-element.ts b/packages/fast-ssr/src/configure-fast-element.ts deleted file mode 100644 index 6dbdf407faf..00000000000 --- a/packages/fast-ssr/src/configure-fast-element.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { - Compiler, - ElementController, - ElementStyles, - Updates, - ViewBehaviorFactory, -} from "@microsoft/fast-element"; -import { SSRElementController } from "./element-controller.js"; -import { FASTSSRStyleStrategy } from "./styles/style-strategy.js"; -import { SSRView } from "./view.js"; - -Compiler.setDefaultStrategy( - ( - html: string | HTMLTemplateElement, - factories: Record - ) => { - if (typeof html !== "string") { - throw new Error( - "SSR compiler does not support HTMLTemplateElement templates" - ); - } - - return new SSRView(html, factories) as any; - } -); - -ElementStyles.setDefaultStrategy(FASTSSRStyleStrategy); - -// Set update mode to synchronous, so that mutations happen immediately. -// This is required due to the synchronous nature of rendering templates -// to a string. -Updates.setMode(false); - -ElementController.setStrategy(SSRElementController); diff --git a/packages/fast-ssr/src/declarative-shadow-dom-polyfill.ts b/packages/fast-ssr/src/declarative-shadow-dom-polyfill.ts deleted file mode 100644 index cd233b3707d..00000000000 --- a/packages/fast-ssr/src/declarative-shadow-dom-polyfill.ts +++ /dev/null @@ -1,38 +0,0 @@ -// Reference: https://web.dev/declarative-shadow-dom/ - -/** - * Provides style and JavaScript code snippets for polyfills related - * to Declarative Shadow DOM (DSD). - * @beta - */ -export const DeclarativeShadowDOMPolyfill = Object.freeze({ - /** - * Styles that hide undefined elements, taking account of the - * fact that undefined elements with DSD should not be hidden. - * @remarks - * These styles should be used in a style element tag in the head - * of the HTML document. - */ - undefinedElementStyles: `:not(:defined) > template[shadowroot] ~ * { - display: none; -}` as string, - /** - * A JavaScript polyfill for DSD that recursively converts all templates - * in the document with the shadowroot attribute into actual shadow roots. - * @remarks - * This is a one-time operation that should be placed at the end of the SSR'd - * HTML but before any other scripts run. - */ - nonStreamingTemplateUpgrade: - `if (!HTMLTemplateElement.prototype.hasOwnProperty('shadowRoot')) { - (function attachShadowRoots(root) { - root.querySelectorAll("template[shadowroot]").forEach(template => { - const mode = template.getAttribute("shadowroot"); - const shadowRoot = template.parentNode.attachShadow({ mode }); - shadowRoot.appendChild(template.content); - template.remove(); - attachShadowRoots(shadowRoot); - }); - })(document); -}` as string, -}); diff --git a/packages/fast-ssr/src/dom-shim.spec.ts b/packages/fast-ssr/src/dom-shim.spec.ts deleted file mode 100644 index ff73206d96d..00000000000 --- a/packages/fast-ssr/src/dom-shim.spec.ts +++ /dev/null @@ -1,184 +0,0 @@ -import "./install-dom-shim.js"; -import { deepStrictEqual, doesNotThrow, ok, strictEqual } from "node:assert/strict"; -import { describe, test } from "node:test"; -import { FASTElement, html } from "@microsoft/fast-element"; -import { createWindow } from "./dom-shim.js"; -import fastSSR from "./exports.js"; -import { uniqueElementName } from "@microsoft/fast-element/testing.js"; - -describe("createWindow", () => { - test("should create a window with a document property that is an instance of the window's Document constructor", () => { - const window = createWindow(); - - strictEqual(window.document instanceof (window.Document as any), true); - - class MyDocument {} - const windowOverride = createWindow({ Document: MyDocument }); - strictEqual(windowOverride.document instanceof MyDocument, true); - }); - test("should create a window with a customElements property that is an instance of the window's CustomElementRegistry constructor", () => { - const window = createWindow(); - - strictEqual( - window.customElements instanceof (window.CustomElementRegistry as any) - , true); - - class MyRegistry {} - const windowOverride = createWindow({ CustomElementRegistry: MyRegistry }); - strictEqual(windowOverride.customElements instanceof MyRegistry, true); - }); -}); - -describe("The DOM shim", () => { - test(`should support construction and connection of a component and template during SSR rendering`, () => { - class MyComponent extends FASTElement {} - - const name = "my-component"; - - MyComponent.define({ - name, - template: html`` - }); - - const { templateRenderer } = fastSSR(); - const templateString = `<${name}>`; - doesNotThrow(() => templateRenderer.render(templateString)); - }); - - describe("has a CSSStyleSheet implementation", () => { - test("that is constructable", () => { - doesNotThrow(() => new CSSStyleSheet()); - }); - test("that supports adding :host{} and :root{} rules", () => { - const sheet = new CSSStyleSheet(); - const hostIndex = sheet.insertRule(":host{}"); - strictEqual(sheet.cssRules[hostIndex].cssText, ":host { }"); - const rootIndex = sheet.insertRule(":root{}"); - strictEqual(sheet.cssRules[rootIndex].cssText, ":root { }"); - }); - - describe("with rule implementations", () => { - test("that support setting properties from the style declaration", () => { - const sheet = new CSSStyleSheet(); - const index = sheet.insertRule(":host{}"); - const rule = sheet.cssRules[index] as CSSStyleRule; - rule.style.setProperty("--test", "value"); - - strictEqual(rule.cssText, ":host { --test: value; }"); - }); - test("that support removing properties from the style declaration", () => { - const sheet = new CSSStyleSheet(); - const index = sheet.insertRule(":host{}"); - const rule = sheet.cssRules[index] as CSSStyleRule; - rule.style.setProperty("--test", "value"); - rule.style.removeProperty("--test"); - - strictEqual(rule.cssText, ":host { }"); - }); - }); - }); - - describe("has a matchMedia method", () => { - test("that can returns the MediaQueryList supplied to createWindow", () => { - class MyMediaQueryList {} - - const win: any = createWindow({ MediaQueryList: MyMediaQueryList }); - const list = win.matchMedia(); - - ok(list instanceof MyMediaQueryList); - }); - }); - - describe("DOMTokenList", () => { - class TestElement extends FASTElement {} - TestElement.define({ name: uniqueElementName() }); - - test("adds a token", () => { - const element = new TestElement(); - const cList = element.classList; - - cList.toggle("c1"); - ok(cList.contains("c1"), "adds a token that is not present"); - - deepStrictEqual(cList.toggle("c2"), - true - , "returns true when token is added"); - }); - - test("removes a token", () => { - const element = new TestElement(); - const cList = element.classList; - - cList.add("c1"); - cList.toggle("c1"); - - ok(!cList.contains("c1"), "removes a token that is present"); - - cList.add("c2"); - deepStrictEqual( - cList.toggle("c2"), false, "return false when token is removed" - ); - }); - - test("adds token with second argument", () => { - const element = new TestElement(); - const cList = element.classList; - - cList.toggle("c1", true); - ok(cList.contains("c1"), "adds a token"); - - deepStrictEqual( - cList.toggle("c2", true), true, "returns true when token is added" - ); - - cList.add("c3"); - cList.toggle("c3", true); - - ok( - cList.contains("c3"), "does not remove a token that is already present" - ); - - cList.add("c4"); - - deepStrictEqual( - cList.toggle("c4", true), true, "returns true when token is already present" - ); - }); - - test("removes token with second argument", () => { - const element = new TestElement(); - const cList = element.classList; - - cList.add("c1"); - cList.toggle("c1", false); - - ok(!cList.contains("c1"), "removes a token"); - - deepStrictEqual( - cList.toggle("c2", false), false, "returns false when token is removed" - ); - - cList.toggle("c3", false); - - ok( - !cList.contains("c3"), "does not add a token that is not present" - ); - - deepStrictEqual( - cList.toggle("c4", false), false, "returns false when token was not present" - ); - }); - - test("removes duplicated tokens", () => { - const element = new TestElement(); - element.className = "ho ho ho"; - - const cList = element.classList; - cList.remove("ho"); - ok( - !cList.contains("ho"), "should remove all instances of 'ho'" - ); - deepStrictEqual(element.className, ""); - }); - }); -}); diff --git a/packages/fast-ssr/src/dom-shim.ts b/packages/fast-ssr/src/dom-shim.ts deleted file mode 100644 index 945853b50a6..00000000000 --- a/packages/fast-ssr/src/dom-shim.ts +++ /dev/null @@ -1,443 +0,0 @@ -/** - * This file was heavily inspired by {@link https://github.com/lit/lit/tree/main/packages/labs/ssr} with some adjustments made. - * Please see {@link ../ACKNOWLEDGEMENTS.md} - */ - -import { shouldBubble } from "./event-utilities.js"; - -/** - * @beta - */ -export class Node extends EventTarget {} - -/** - * @beta - */ -export class Element extends Node {} - -function checkTokenAndGetIndex(classList: DOMTokenList, token: string) { - if (token === "") { - throw new Error("The token must not be empty."); - } - - if (/\s/.test(token)) { - throw new Error("The token must not contain space characters."); - } - - return classList.indexOf(token); -} - -/* - * Based on classList.js: Cross-browser full element.classList implementation. - * 1.2.20171210 - * - * Credit to Eli Grey, http://eligrey.com - * License: Dedicated to the public domain. - * See https://github.com/eligrey/classList.js/blob/master/LICENSE.md - */ - -/** - * @beta - */ -export class DOMTokenList { - private tokens: string[] = []; - - public constructor(private element: HTMLElement, private attributeName: string) { - const trimmedClasses = (element.getAttribute(attributeName) || "").trim(); - const classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []; - - for (let i = 0, len = classes.length; i < len; i++) { - this.tokens.push(classes[i]); - } - } - - public item(i: number) { - return this.tokens[i] || null; - } - - public contains(token: string) { - return ~checkTokenAndGetIndex(this, token + ""); - } - - public indexOf(token: string) { - return this.tokens.indexOf(token); - } - - public add(...tokens: string[]) { - const length = tokens.length; - let index = 0; - let updated = false; - - do { - const token = tokens[index] + ""; - - if (!~checkTokenAndGetIndex(this, token)) { - this.tokens.push(token); - updated = true; - } - } while (++index < length); - - if (updated) { - this.updateClassName(); - } - } - - public remove(...tokens: string[]) { - const length = tokens.length; - let index = 0; - let updated = false; - - do { - const token = tokens[index] + ""; - let result = checkTokenAndGetIndex(this, token); - - while (~result) { - this.tokens.splice(result, 1); - updated = true; - result = checkTokenAndGetIndex(this, token); - } - } while (++index < length); - - if (updated) { - this.updateClassName(); - } - } - - public toggle(token: string, force: boolean): boolean { - const result = this.contains(token); - const method = result ? force !== true && "remove" : force !== false && "add"; - - if (method) { - this[method](token); - } - - if (force === true || force === false) { - return force; - } else { - return !result; - } - } - - public replace(token: string, replacement: string) { - const index = checkTokenAndGetIndex(this, token + ""); - - if (~index) { - this.tokens.splice(index, 1, replacement); - this.updateClassName(); - } - } - - public toString(): string { - return this.tokens.join(" "); - } - - private updateClassName() { - this.element.setAttribute(this.attributeName, this.toString()); - } -} - -/** - * @beta - */ -export abstract class HTMLElement extends Element { - private static elementAttributes: WeakMap> = - new WeakMap(); - private static getOrCreateAttributesForElement(element: HTMLElement) { - let attrs = HTMLElement.elementAttributes.get(element); - if (!attrs) { - HTMLElement.elementAttributes.set(element, (attrs = new Map())); - } - return attrs; - } - - private _shadowRoot: null | ShadowRoot = null; - - get attributes() { - return Array.from(HTMLElement.getOrCreateAttributesForElement(this)).map( - ([name, value]) => ({ - name, - value, - }) - ); - } - - get shadowRoot() { - return this._shadowRoot; - } - - get part(): DOMTokenList { - return new DOMTokenList(this, "part"); - } - - get classList(): DOMTokenList { - return new DOMTokenList(this, "class"); - } - - get className(): string | null { - return this.getAttribute("class"); - } - - set className(value: string | null) { - if (value === null) { - this.removeAttribute("class"); - } else { - this.setAttribute("class", value); - } - } - - abstract attributeChangedCallback?( - name: string, - old: string | null, - value: string | null - ): void; - - setAttribute(name: string, value: string) { - HTMLElement.getOrCreateAttributesForElement(this).set(name, value); - } - - removeAttribute(name: string) { - HTMLElement.getOrCreateAttributesForElement(this).delete(name); - } - - hasAttribute(name: string) { - return HTMLElement.getOrCreateAttributesForElement(this).has(name); - } - - attachShadow(init: ShadowRootInit): ShadowRoot { - const shadowRoot = { host: this }; - if (init && init.mode === "open") { - this._shadowRoot = shadowRoot; - } - return shadowRoot; - } - - getAttribute(name: string) { - const value = HTMLElement.getOrCreateAttributesForElement(this).get(name); - return value === undefined ? null : value; - } -} - -/** - * @beta - */ -export interface CustomHTMLElement { - new (): HTMLElement; - observedAttributes?: string[]; -} - -/** - * @beta - */ -export class ShadowRoot {} - -/** - * @beta - */ -export class Document extends Node { - public adoptedStyleSheets: ReadonlyArray = []; - createTreeWalker() { - return {}; - } - createTextNode() { - return {}; - } - createElement() { - return {}; - } - - public dispatchEvent(event: Event): boolean { - let canceled = super.dispatchEvent(event); - - if (shouldBubble(event)) { - canceled = window.dispatchEvent(event); - } - - return canceled; - } -} - -/** - * @beta - */ -export class CustomEvent extends Event { - public detail: T | null = null; - constructor(type: string, init?: CustomEventInit) { - super(type, init); - - if (init && "detail" in init) { - this.detail = init.detail as T; - } - } -} - -/** - * @beta - */ -export class CSSStyleRule { - public selectorText: string | undefined; - public readonly style = new CSSStyleDeclaration(); - - public get cssText(): string { - if (typeof this.selectorText !== "string") { - throw new Error( - "Cannot format cssText for CSSStyleRule. No selectorText property is assigned." - ); - } - - return `${this.selectorText} { ${this.style.cssText} }`; - } -} - -/** - * @beta - */ -export class CSSStyleDeclaration { - private rules = new Map(); - public setProperty(name: string, value: string = "") { - this.rules.set(name, value); - } - public removeProperty(name: string) { - this.rules.delete(name); - } - - public get cssText() { - let text = ""; - - for (const [key, value] of this.rules) { - text += `${key}: ${value};`; - } - - return text; - } -} - -/** - * @beta - */ -export class CSSStyleSheet { - replace() {} - public readonly cssRules: CSSRule[] = []; - insertRule(rule: string, index: number = 0) { - const selectorText = rule.split("{")[0]; - const styleRule = new window.CSSStyleRule(); - styleRule.selectorText = selectorText; - this.cssRules.splice(index, 0, styleRule); - - return index; - } -} - -/** - * @beta - */ -export type CustomElementRegistration = { - ctor: { new (): HTMLElement }; - observedAttributes: string[]; -}; - -/** - * @beta - */ -export class CustomElementRegistry { - private __definitions = new Map(); - - define(name: string, ctor: CustomHTMLElement) { - this.__definitions.set(name, { - ctor, - observedAttributes: (ctor as CustomHTMLElement).observedAttributes ?? [], - }); - } - - get(name: string) { - const definition = this.__definitions.get(name); - return definition && definition.ctor; - } -} - -/** - * @beta - */ -export class MutationObserver { - observe() {} -} - -/** - * Shim of MediaQueryList. - * {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList} */ -export class MediaQueryList { - /** No-op */ - addEventListener() {} - - /** No-op */ - removeEventListener() {} - - /** Always false */ - matches = false; -} - -/** - * @beta - */ -export class Window extends EventTarget { - public Node = Node; - public Element = Element; - public HTMLElement = HTMLElement; - public Document = Document; - public CustomEvent = CustomEvent; - public CSSStyleSheet = CSSStyleSheet; - public CSSStyleDeclaration = CSSStyleDeclaration; - public CSSStyleRule = CSSStyleRule; - public ShadowRoot = ShadowRoot; - public CustomElementRegistry = CustomElementRegistry; - public MutationObserver = MutationObserver; - public MediaQueryList = MediaQueryList; - public matchMedia = () => new this.MediaQueryList(); - - // Defined in constructor - public window: unknown; - public document: unknown; - public customElements: unknown; - public dispatchEvent: any; - public addEventListener: any; - public removeEventListener: any; - - constructor(props?: Record) { - super(); - - /** - * Methods of EventTarget must be assigned explicitly, otherwise they get omitted - * when the window is merged into the `globalThis` in {@link installWindowOnGlobal}. - */ - this.dispatchEvent = EventTarget.prototype.dispatchEvent.bind(this); - this.addEventListener = EventTarget.prototype.addEventListener.bind(this); - this.removeEventListener = EventTarget.prototype.removeEventListener.bind(this); - - Object.assign(this, props); - this.window = this; - this.document = new this.Document(); - this.customElements = new this.CustomElementRegistry(); - } -} - -/** - * Creates a window object. - * @param props - Additional properties to expose on the window. - * - * @beta - */ -export function createWindow>(props?: T): Window & T { - return new Window(props) as Window & T; -} - -/** - * Installs a window object on the global, exposing properties directly on globalThis and globalthis.window - * @param window - The Window object to install - * - * @beta - */ -export function installWindowOnGlobal(window: Record) { - if (globalThis.window === undefined) { - Object.assign(globalThis, window); - globalThis.window = globalThis as any; - } -} diff --git a/packages/fast-ssr/src/element-controller.ts b/packages/fast-ssr/src/element-controller.ts deleted file mode 100644 index b12dd9390ac..00000000000 --- a/packages/fast-ssr/src/element-controller.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ElementController } from "@microsoft/fast-element"; - -export class SSRElementController extends ElementController { - disconnect(): void { - super.disconnect(); - - // remove all behaviors to avoid memory leak - if (this.behaviors !== null) { - for (const [behavior] of this.behaviors) { - this.removeBehavior(behavior, true); - } - } - } -} diff --git a/packages/fast-ssr/src/element-renderer/element-renderer.spec.ts b/packages/fast-ssr/src/element-renderer/element-renderer.spec.ts deleted file mode 100644 index 7bc92b5cfd0..00000000000 --- a/packages/fast-ssr/src/element-renderer/element-renderer.spec.ts +++ /dev/null @@ -1,551 +0,0 @@ -import "../install-dom-shim.js"; - -import { deepStrictEqual, doesNotThrow, ok, strictEqual, throws } from "node:assert/strict"; -import { describe, test } from "node:test"; -import { attr, css, customElement, FASTElement, html, observable, when } from "@microsoft/fast-element"; -import { PendingTaskEvent } from "@microsoft/fast-element/pending-task.js"; -import { uniqueElementName } from "@microsoft/fast-element/testing.js"; -import fastSSR from "../exports.js"; -import { consolidate, consolidateAsync } from "../test-utilities/consolidate.js"; -import { SyncFASTElementRenderer } from "./fast-element-renderer.js"; - -@customElement({ - name: "bare-element", -}) -export class BareElement extends FASTElement {} -@customElement({ - name: "styled-element", - styles: css`:host { display: block; }${css`:host { color: red; }`} - ` -}) -export class StyledElement extends FASTElement {} -@customElement({ - name: "host-binding-element", - template: html` - - ` -}) -export class HostBindingElement extends FASTElement {} - -describe("FallbackRenderer", () => { - // Define custom element that is not a FAST elmeent. - const name = uniqueElementName(); - customElements.define(name, class extends HTMLElement{}); - describe("rendering an element with attributes", () => { - test("should not render the attribute when binding evaluates null", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - <${html.partial(name)} attr="${x => null}"> - `)); - strictEqual(result, ` - <${name} > - `); - }); - - test("should not render the attribute when the binding evaluates undefined", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - <${html.partial(name)} attr="${x => undefined}"> - `)); - strictEqual(result, ` - <${name} > - `); - }); - - test("should render a boolean attribute with the values of true or false", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - <${html.partial(name)} ?attr="${x => true}"> - <${html.partial(name)} ?attr="${x => false}"> - `)); - strictEqual(result, ` - <${name} attr> - <${name} > - `); - }); - - test("should render a non-boolean attribute with the values of true or false", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - <${html.partial(name)} aria-expanded="${x => true}"> - <${html.partial(name)} aria-expanded="${x => false}"> - `)); - strictEqual(result, ` - <${name} aria-expanded="true"> - <${name} aria-expanded="false"> - `); - }); - - test("should render an attribute with the value of a number", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - <${html.partial(name)} number="${x => 12}"> - <${html.partial(name)} number="${x => NaN}"> - `)); - strictEqual(result, ` - <${name} number="12"> - <${name} number="NaN"> - `); - }); - - test("should render an attribute with a string value", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - <${html.partial(name)} attr="${x => 'my-str-value'}"> - `)); - strictEqual(result, ` - <${name} attr="my-str-value"> - `); - }); - - test("should throw error when rendering an attribute with an object value", () => { - const { templateRenderer } = fastSSR(); - - throws(() => { - consolidate(templateRenderer.render(html`<${html.partial(name)} attr="${x => ({ key: 'my-value' })}">`)); - }) - }); - }); -}); - -describe("FASTElementRenderer", () => { - describe("should have a 'matchesClass' method", () => { - test("that returns true when invoked with a class that extends FASTElement ", () => { - class MyElement extends FASTElement {} - strictEqual(SyncFASTElementRenderer.matchesClass(MyElement, "", new Map()), true); - }); - test("that returns false when invoked with a class that does not extend FASTElement ", () => { - class MyElement extends HTMLElement {} - strictEqual(SyncFASTElementRenderer.matchesClass(MyElement, "", new Map()), false); - }); - - test("should return false when the provided class has been disabled", () => { - class MyElement extends FASTElement {} - const { ElementRenderer } = fastSSR(); - - ElementRenderer.disable(MyElement); - - strictEqual(ElementRenderer.matchesClass(MyElement, "", new Map()), false) - }); - test("should return false when the provided tag-name has been disabled", () => { - const name = uniqueElementName(); - class MyElement extends FASTElement {} - const { ElementRenderer } = fastSSR(); - - ElementRenderer.disable(name); - - strictEqual(ElementRenderer.matchesClass(MyElement, name, new Map()), false) - }); - test("should return false when the provided element definition has been disabled", () => { - const name = uniqueElementName(); - class MyElement extends FASTElement {} - const definition = MyElement.compose(name); - const { ElementRenderer } = fastSSR(); - - ElementRenderer.disable(definition); - - strictEqual(ElementRenderer.matchesClass(MyElement, name, new Map()), false) - }); - }); - - describe("rendering stylesheets", () => { - test(`should render stylesheets as 'style' elements by default`, () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html``)); - strictEqual(result, ``); - }); - test.skip(`should render stylesheets as 'fast-style' elements when configured`, () => { - const { templateRenderer } = fastSSR(/* Replace w/ configuration when fast-style work is complete{useFASTStyle: true}*/); - const result = consolidate(templateRenderer.render(html``)); - strictEqual(result, ``); - }); - }); - - describe("with host bindings", () => { - test("should render attributes on the root of a template element to the host element", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - - `)); - strictEqual(result, ` - - `); - }); - - test("should not evaluate event bindings on the host", () => { - const { templateRenderer } = fastSSR(); - const name = uniqueElementName(); - FASTElement.define({name , template: html``}); - - doesNotThrow(() => { - consolidate(templateRenderer.render(`<${name}>`)); - }) - }); - }) - - describe("rendering an element with attributes", () => { - test("should not render the attribute when binding evaluates null", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - - `)); - strictEqual(result, ` - - `); - }); - test("should not render the attribute when the binding evaluates undefined", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - - `)); - strictEqual(result, ` - - `); - }); - - test("should render a boolean attribute with the values of true or false", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - - - `)); - strictEqual(result, ` - - - `); - }); - - test("should render a non-boolean attribute with the values of true or false", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - - - `)); - strictEqual(result, ` - - - `); - }); - - test("should render an attribute with the value of a number", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - - - `)); - strictEqual(result, ` - - - `); - }); - - test("should render an attribute with a string value", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html` - - `)); - strictEqual(result, ` - - `); - }); - - test("should throw error when rendering an attribute with an object value", () => { - const { templateRenderer } = fastSSR(); - try { - consolidate(templateRenderer.render(html``)); - } catch (error) { - deepStrictEqual(error, new Error("Cannot assign attribute 'attr' for element bare-element.")); - } - }); - }); - - describe("emitting events", () => { - - @customElement("test-event-dispatch") - class TestEventDispatch extends FASTElement { - @attr({attribute: "event-detail"}) - eventDetail: string = ""; - - @attr({ attribute: "listen-self", mode: "boolean"}) - listenSelf: boolean = false; - - @attr({ attribute: "stop-immediate-prop", mode: "boolean"}) - stopImmediateProp: boolean = false; - - @attr({ attribute: "stop-prop", mode: "boolean"}) - stopProp: boolean = false; - - connectedCallback(): void { - super.connectedCallback(); - const e = new CustomEvent<{ data: string }>("test-event", {bubbles: true, detail: { data: ""}}) - - if (this.listenSelf) { - this.addEventListener("test-event", (e: any) => { - e.detail.data = "listen-self-success"; - e.stopPropagation(); - }); - } - - if (this.stopProp) { - this.addEventListener("test-event", (e: any) => { - e.detail.data = "stop-prop-success"; - e.stopPropagation(); - }); - } - if (this.stopImmediateProp) { - this.addEventListener("test-event", (e: any) => { - e.detail.data = "stop-immediate-prop-success"; - e.stopImmediatePropagation(); - }); - this.addEventListener("test-event", (e: any) => { - e.detail.data = "stop-immediate-prop-failure"; - }); - } - - this.dispatchEvent(e); - - this.eventDetail = e.detail.data || ""; - } - } - - @customElement("test-event-listener") - class TestEventListener extends FASTElement { - @attr - data: string = "default" - - connectedCallback() { - super.connectedCallback(); - this.addEventListener("test-event", (e: Event) => { - ( e as CustomEvent<{ data: string }> ).detail.data = this.data; - }) - } - } - test("An element dispatching an event should get it's own handler fired", () => { - const { templateRenderer } = fastSSR(); - const result = consolidate(templateRenderer.render(html`` )); - strictEqual(result, ``) - }); - test("An ancestor with a handler should get it's handler invoked if the event bubbles", () => { - const { templateRenderer } = fastSSR(); - - const result = consolidate(templateRenderer.render(html``)); - strictEqual(result, ``) - }); - test("Should bubble events to the document", () => { - document.addEventListener("test-event", (e) => { - (e as any).detail.data = "document-success"; - }); - const { templateRenderer } = fastSSR(); - - const result = consolidate(templateRenderer.render(html``)); - - strictEqual(result, ``); - }); - test("Should bubble events to the window", () => { - window.addEventListener("test-event", (e) => { - (e as any).detail.data = "window-success"; - }); - const { templateRenderer } = fastSSR(); - - const result = consolidate(templateRenderer.render(html``)); - strictEqual(result, ``); - }); - test("Should not bubble an event that invokes event.stopImmediatePropagation()", () => { - const { templateRenderer } = fastSSR(); - - const result = consolidate(templateRenderer.render(html``)); - strictEqual(result, ``) - }); - test("Should not bubble an event that invokes event.stopPropagation()", () => { - const { templateRenderer } = fastSSR(); - - const result = consolidate(templateRenderer.render(html``)); - strictEqual(result, ``) - }); - }); - - describe("rendering asynchronously", () => { - test("should support attribute mutation for the element as a result of PendingTask events", async () => { - const name = uniqueElementName(); - @customElement({ - name, - }) - class MyElement extends FASTElement { - connectedCallback(): void { - super.connectedCallback(); - this.dispatchEvent(new PendingTaskEvent(new Promise((resolve) => { - window.setTimeout(() => { - this.setAttribute("async-resolved", ""); - resolve(); - }, 20); - }))); - } - } - - const template = html`<${html.partial(name)}>`; - const { templateRenderer } = fastSSR({renderMode: "async"}); - - strictEqual(await consolidateAsync(templateRenderer.render(template)), `<${name} async-resolved>`) - }); - - - test("should throw when the element catches rejected PendingTaskEvents", async () => { - const name = uniqueElementName(); - @customElement({ - name, - }) - class MyElement extends FASTElement { - connectedCallback(): void { - super.connectedCallback(); - this.dispatchEvent(new PendingTaskEvent(new Promise((resolve, reject) => { - window.setTimeout(() => { - this.setAttribute("async-reject", ""); - reject(new Error()); - }, 20); - }))); - } - } - - const template = html`<${html.partial(name)}>`; - const { templateRenderer } = fastSSR({renderMode: "async"}); - try { - await consolidateAsync(templateRenderer.render(template)) - strictEqual("didn't error", "errored"); - } catch(e) { - strictEqual("errored", "errored"); - } - }); - test("should await multiple PendingTaskEvents", async () => { - const name = uniqueElementName(); - @customElement({ - name, - }) - class MyElement extends FASTElement { - connectedCallback(): void { - super.connectedCallback(); - this.dispatchEvent(new PendingTaskEvent(new Promise((resolve) => { - window.setTimeout(() => { - this.setAttribute("async-resolved-one", ""); - resolve(); - }, 20); - }))); - this.dispatchEvent(new PendingTaskEvent(new Promise((resolve) => { - window.setTimeout(() => { - this.setAttribute("async-resolved-two", ""); - resolve(); - }, 30); - }))); - } - } - - const template = html`<${html.partial(name)}>`; - const { templateRenderer } = fastSSR({renderMode: "async"}); - - strictEqual(await consolidateAsync(templateRenderer.render(template)), `<${name} async-resolved-one async-resolved-two>`) - }); - test("should render template content only displayed after PendingTaskEvent is resolved", async () => { - const name = uniqueElementName(); - @customElement({ - name, - template: html`${when(x => x.renderContent, html`

    Async content success

    `)}` - }) - class MyElement extends FASTElement { - @observable - renderContent: boolean = false; - connectedCallback(): void { - super.connectedCallback(); - this.dispatchEvent(new PendingTaskEvent(new Promise((resolve) => { - window.setTimeout(() => { - this.renderContent = true; - resolve(); - }, 20); - }))); - } - } - - const template = html`<${html.partial(name)}>`; - const { templateRenderer } = fastSSR({renderMode: "async"}); - - strictEqual(await consolidateAsync(templateRenderer.render(template)), `<${name}>`) - }); - test("should support nested async rendering scenarios", async () => { - const name = uniqueElementName(); - @customElement({ - name, - template: html`` - }) - class MyElement extends FASTElement { - @observable - renderContent: boolean = false; - connectedCallback(): void { - super.connectedCallback(); - this.dispatchEvent(new PendingTaskEvent(new Promise((resolve) => { - window.setTimeout(() => { - this.setAttribute("async-resolved", "") - resolve(); - }, 20); - }))); - } - } - - const template = html`<${html.partial(name)}><${html.partial(name)}>`; - const { templateRenderer } = fastSSR({renderMode: "async"}); - - strictEqual(await consolidateAsync(templateRenderer.render(template)), `<${name} async-resolved><${name} async-resolved>`) - }); - - test("should support asyncronously calling FASTElement.connectedCallback", async () => { - const name = uniqueElementName(); - @customElement({ - name, - template: html`

    attr value: ${x => x.value}

    ` - }) - class MyElement extends FASTElement { - @attr - value: string = ""; - - connectedCallback(): void { - this.asyncConnectedCallback(); - } - - async asyncConnectedCallback() { - this.dispatchEvent(new PendingTaskEvent(new Promise((resolve) => { - window.setTimeout(() => { - super.connectedCallback(); - resolve(); - }, 20); - }))); - } - } - - - const { templateRenderer } = fastSSR({renderMode: "async"}); - const template = `<${name} value="hello-world">`; - strictEqual(await consolidateAsync(templateRenderer.render(template)), `<${name} value="hello-world">`) - }) - }); - - test("should match FAST elements that extend base-classes created from `FASTElement.from()`", () => { - const BaseClass = FASTElement.from(HTMLElement); - class MyElement extends BaseClass {} - - const name = uniqueElementName(); - FASTElement.define(MyElement, name); - - const { ElementRenderer } = fastSSR(); - - strictEqual(ElementRenderer.matchesClass(MyElement, name, new Map()), true) - }) - - describe("with hydration markup enabled", () => { - test("should emit the 'needs-hydration' attribute from `renderAttributes()`", () => { - const { ElementRenderer, templateRenderer } = fastSSR({ emitHydratableMarkup: true}); - const name = uniqueElementName(); - - FASTElement.define(name); - const renderer = new ElementRenderer(name, templateRenderer.createRenderInfo()); - - ok(consolidate(renderer.renderAttributes()).split(" ").includes("needs-hydration")); - }); - }) -}); diff --git a/packages/fast-ssr/src/element-renderer/element-renderer.ts b/packages/fast-ssr/src/element-renderer/element-renderer.ts deleted file mode 100644 index d8946a34406..00000000000 --- a/packages/fast-ssr/src/element-renderer/element-renderer.ts +++ /dev/null @@ -1,163 +0,0 @@ -/** - * This file was ported from {@link https://github.com/lit/lit/tree/main/packages/labs/ssr}. - * Please see {@link ../ACKNOWLEDGEMENTS.md} - */ -import { DOM, observable } from "@microsoft/fast-element"; -import { RenderInfo } from "../render-info.js"; -import { escapeHtml } from "../escape-html.js"; -import { HTMLElement as ShimHTMLElement } from "../dom-shim.js"; -import { shouldBubble } from "../event-utilities.js"; -import { AttributesMap, ElementRenderer } from "./interfaces.js"; - -/** - * @beta - */ -export abstract class DefaultElementRenderer - implements Omit -{ - private parent: ElementRenderer | null = null; - private restoreElementDispatchEvent: (() => void) | null = null; - @observable - abstract element?: HTMLElement; - elementChanged() { - this.restoreElementDispatchEvent?.(); - if (this.element) { - const element = this.element; - const dispatch = element.dispatchEvent; - Reflect.defineProperty(element, "dispatchEvent", { - value: (event: Event) => { - let canceled = dispatch.call(element, event); - - if (shouldBubble(event)) { - if (this.parent) { - canceled = this.parent.dispatchEvent(event); - } else if (element instanceof ShimHTMLElement) { - // Only emit on document if the the element is the DOM shim's element. - // Otherwise, the installed DOM should implement it's own behavior for bubbling - // an event from an element to the document and window. - canceled = document.dispatchEvent(event); - } - } - - return canceled; - }, - }); - this.restoreElementDispatchEvent = () => { - Reflect.defineProperty(element, "dispatchEvent", { - value: dispatch, - }); - this.restoreElementDispatchEvent = null; - }; - } - } - - /** - * Should return true when the renderer should handle rendering for a custom element ctor or tag name. - * @param ctor - the custom element class - * @param tagName - the custom element tag name - * @param attributes - the attribute map - * @returns - */ - static matchesClass( - ctor: typeof HTMLElement, - tagName: string, - attributes: AttributesMap - ): boolean { - return false; - } - - constructor(public readonly tagName: string, renderInfo?: RenderInfo) { - this.parent = renderInfo?.customElementInstanceStack.at(-1) || null; - } - - connectedCallback() {} - disconnectedCallback() { - this.restoreElementDispatchEvent?.(); - this.parent = null; - delete this.element; - } - abstract attributeChangedCallback( - name: string, - prev: string | null, - next: string | null - ): void; - - public dispatchEvent(event: Event): boolean { - return this.element?.dispatchEvent(event) || false; - } - - /** - * Sets a property for the element if it exists. - */ - public setProperty(name: string, value: unknown) { - if (this.element) { - (this.element as any)[name] = value; - } - } - - /** - * Sets an attribute for the element if it exists. - */ - public setAttribute(name: string, value: string) { - if (this.element) { - const prev = this.element.getAttribute(name); - if (value !== prev) { - DOM.setAttribute(this.element, name, value); - this.attributeChangedCallback(name, prev, value); - } - } - } -} - -export function renderAttribute(name: string, value: unknown, tagName?: string) { - if (value === "" || value === undefined || value === null) { - return ` ${name}`; - } else if (typeof value === "string") { - return ` ${name}="${escapeHtml(value)}"`; - } else if (typeof value === "boolean" || typeof value === "number") { - return ` ${name}="${value}"`; - } else { - throw new Error(`Cannot assign attribute '${name}' for element ${tagName}.`); - } -} - -/** - * An ElementRenderer used as a fallback in the case where a custom element is - * either unregistered or has no other matching renderer. - */ -export class FallbackRenderer extends DefaultElementRenderer implements ElementRenderer { - public element?: HTMLElement | undefined; - - /** - * When true, instructs the ElementRenderer to yield the `defer-hydration` attribute for - * rendered elements. - */ - public deferHydration = false; - - private readonly _attributes: { [name: string]: string } = {}; - - public setAttribute(name: string, value: string) { - if (value === undefined || value === null) { - this.removeAttribute(name); - } else { - this._attributes[name] = value; - } - } - - public removeAttribute(name: string) { - delete this._attributes[name]; - } - - public *renderAttributes(): IterableIterator { - if (this.deferHydration) { - yield " defer-hydration"; - } - for (const [name, value] of Object.entries(this._attributes)) { - yield renderAttribute(name, value, this.element?.tagName); - } - } - - attributeChangedCallback() {} - /* eslint-disable-next-line */ - *renderShadow() {} -} diff --git a/packages/fast-ssr/src/element-renderer/fast-element-renderer.ts b/packages/fast-ssr/src/element-renderer/fast-element-renderer.ts deleted file mode 100644 index 84581fa3321..00000000000 --- a/packages/fast-ssr/src/element-renderer/fast-element-renderer.ts +++ /dev/null @@ -1,336 +0,0 @@ -import { - DOM, - DOMAspect, - ExecutionContext, - FASTElement, - FASTElementDefinition, - HostController, - Observable, - observable, -} from "@microsoft/fast-element"; -import { PendingTaskEvent } from "@microsoft/fast-element/pending-task.js"; -import { RenderInfo } from "../render-info.js"; -import { StyleRenderer } from "../styles/style-renderer.js"; -import { FASTSSRStyleStrategy } from "../styles/style-strategy.js"; -import { DefaultTemplateRenderer } from "../template-renderer/template-renderer.js"; -import { SSRView } from "../view.js"; -import { DefaultElementRenderer, renderAttribute } from "./element-renderer.js"; -import { AsyncElementRenderer, AttributesMap, ElementRenderer } from "./interfaces.js"; - -/** - * Sinks to apply aspect operations to an element - */ -const sinks: Record void> = { - [DOMAspect.property]: (el: any, name: string, value: any) => { - el[name] = value; - }, - [DOMAspect.attribute]: DOM.setAttribute, - [DOMAspect.booleanAttribute]: DOM.setBooleanAttribute, -}; - -/** - * An {@link ElementRenderer} implementation designed to render components - * built with FAST. - * - */ -abstract class FASTElementRenderer extends DefaultElementRenderer { - /** - * The element instance represented by the {@link FASTElementRenderer}. - */ - public readonly element!: FASTElement; - - /** - * The custom element constructor - */ - public readonly ctor: CustomElementConstructor; - - /** - * A function that decies if given tagName should defer hydration. - * When true, instructs the ElementRenderer to yield the `defer-hydration` attribute for - * rendered elements. - */ - protected abstract deferHydration: (tagName: string) => boolean; - - protected needsHydration: boolean = false; - - /** - * The template renderer to use when rendering a component template - */ - @observable - protected abstract templateRenderer: DefaultTemplateRenderer; - templateRendererChanged() { - if (this.templateRenderer) { - this.needsHydration = this.templateRenderer.emitHydratableMarkup; - } - } - - /** - * Responsible for rendering stylesheets - */ - protected abstract styleRenderer: StyleRenderer; - - protected attributes: AttributesMap = new Map(); - - public static matchesClass( - ctor: typeof HTMLElement, - tagName: string, - attributes: AttributesMap - ): boolean { - return ctor.prototype instanceof FASTElement; - } - - /** - * Indicate to the {@link FASTElementRenderer} that the instance should execute DOM connection behavior. - */ - public connectedCallback(): void { - super.connectedCallback(); - Observable.getNotifier(this.element.$fastController).subscribe( - this, - "isConnected" - ); - - try { - this.element.connectedCallback(); - } catch (e) { - const { tryRecoverFromErrors } = this.templateRenderer; - if (tryRecoverFromErrors) { - this.disableTemplateRendering(); - - if (typeof tryRecoverFromErrors === "function") { - tryRecoverFromErrors(e); - } - } else { - throw e; - } - } - } - - public disconnectedCallback(): void { - super.disconnectedCallback(); - Observable.getNotifier(this.element.$fastController).unsubscribe( - this, - "isConnected" - ); - this.element.disconnectedCallback(); - } - - public handleChange(source: HostController, property: "isConnected") { - if (this.element.$fastController.isConnected) { - const view = this.element.$fastController.view; - - if (view && SSRView.isSSRView(view)) { - if (view.hostStaticAttributes) { - view.hostStaticAttributes.forEach((value, key) => { - this.element.setAttribute(key, value); - }); - } - - if (view.hostDynamicAttributes) { - for (const attr of view.hostDynamicAttributes) { - const aspect = attr.factory.aspectType; - if (aspect in sinks && attr.factory.dataBinding) { - sinks[aspect]( - this.element, - attr.factory.targetAspect, - attr.factory.dataBinding.evaluate( - this.element, - ExecutionContext.default - ) - ); - } - } - } - } - } - } - - /** - * Disables the rendering of the component's template. - */ - protected disableTemplateRendering() { - this.renderShadow = noOpRenderShadow; - this.yieldAttributes = yieldContextualAttributes; - this.needsHydration = false; - } - - /** - * Indicate to the {@link FASTElementRenderer} that an attribute has been changed. - * @param name - The name of the changed attribute - * @param old - The old attribute value - * @param value - The new attribute value - */ - public attributeChangedCallback( - name: string, - old: string | null, - value: string | null - ): void { - this.element.attributeChangedCallback(name, old, value); - } - - public setAttribute(name: string, value: string): void { - super.setAttribute(name, value); - this.attributes.set(name, value); - } - - /** - * Constructs a new {@link FASTElementRenderer}. - * @param tagName - the tag-name of the element to create. - */ - constructor(tagName: string, renderInfo: RenderInfo) { - super(tagName, renderInfo); - - const ctor = customElements.get(this.tagName); - - if (ctor) { - this.ctor = ctor; - this.element = new ctor() as FASTElement; - (this.element as any).tagName = tagName; - } else { - throw new Error( - `FASTElementRenderer was unable to find a constructor for a custom element with the tag name '${tagName}'.` - ); - } - } - - /** - * Yield attributes assigned to the elmeent - * - */ - protected *yieldAttributes() { - const { attributes } = this.element; - for ( - let i = 0, name, value; - i < attributes.length && ({ name, value } = attributes[i]); - i++ - ) { - yield renderAttribute(name, value, this.element.tagName); - } - } - - abstract renderShadow: - | ((renderInfo: RenderInfo) => IterableIterator) - | ((renderInfo: RenderInfo) => IterableIterator>); -} - -export abstract class SyncFASTElementRenderer - extends FASTElementRenderer - implements ElementRenderer -{ - renderAttributes = renderAttributesSync; - renderShadow = renderShadow; -} -export abstract class AsyncFASTElementRenderer - extends FASTElementRenderer - implements AsyncElementRenderer -{ - constructor(tagName: string, renderInfo: RenderInfo) { - super(tagName, renderInfo); - - this.element.addEventListener(PendingTaskEvent.type, this.pendingTaskHandler); - } - public *renderAttributes( - this: AsyncFASTElementRenderer - ): IterableIterator> { - if (this.element !== undefined) { - if (this.awaiting.size) { - yield this.pauseRendering() - .then(() => "") - .catch(reason => { - throw reason; - }); - } - - yield* renderAttributesSync.call(this); - } - } - renderShadow = renderShadow; - - private async pauseRendering() { - for (const awaiting of this.awaiting) { - try { - await awaiting; - } catch (e) { - const { tryRecoverFromErrors } = this.templateRenderer; - - if (tryRecoverFromErrors) { - this.disableTemplateRendering(); - - if (typeof tryRecoverFromErrors === "function") { - tryRecoverFromErrors(e); - } - } else { - throw e; - } - } - } - - this.awaiting.clear(); - } - - private awaiting: Set> = new Set(); - - private pendingTaskHandler = (e: Event) => { - if (PendingTaskEvent.isPendingTask(e)) { - this.awaiting.add(e.complete); - } - }; -} - -function* renderAttributesSync(this: FASTElementRenderer): IterableIterator { - yield* this.yieldAttributes(); - - if (this.deferHydration(this.tagName)) { - yield " defer-hydration"; - } - - if (this.needsHydration) { - yield " needs-hydration"; - } -} - -function* renderShadow( - this: FASTElementRenderer, - renderInfo: RenderInfo -): IterableIterator { - const view = this.element.$fastController.view as unknown as SSRView; - const styles = FASTSSRStyleStrategy.getStylesFor(this.element); - - const elementDefinition = FASTElementDefinition.getByType(this.ctor); - const yieldDSD = elementDefinition?.shadowOptions !== undefined; - const yieldBoundaryMarker = - elementDefinition && elementDefinition.shadowOptions === undefined && view; - - if (yieldDSD) { - yield '"; - } else if (yieldBoundaryMarker) { - yield ``; - } -} - -// eslint-disable-next-line -function* noOpRenderShadow() {} -function* yieldContextualAttributes(this: FASTElementRenderer) { - const { attributes } = this; - for (const [key, value] of attributes) { - yield renderAttribute(key, value, this.element.tagName); - } -} diff --git a/packages/fast-ssr/src/element-renderer/interfaces.ts b/packages/fast-ssr/src/element-renderer/interfaces.ts deleted file mode 100644 index 0b911127fae..00000000000 --- a/packages/fast-ssr/src/element-renderer/interfaces.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { FASTElement, FASTElementDefinition } from "@microsoft/fast-element"; -import { RenderInfo } from "../render-info.js"; - -/** - * @beta - */ -export interface ElementRenderer { - readonly tagName: string; - connectedCallback(): void; - disconnectedCallback(): void; - attributeChangedCallback( - name: string, - prev: string | null, - next: string | null - ): void; - dispatchEvent(event: Event): boolean; - setProperty(name: string, value: unknown): void; - setAttribute(name: string, value: string): void; - renderShadow(renderInfo: RenderInfo): IterableIterator; - renderAttributes(): IterableIterator; -} - -/** - * @beta - */ -export interface AsyncElementRenderer - extends Omit { - renderShadow(renderInfo: RenderInfo): IterableIterator>; - renderAttributes(): IterableIterator>; -} - -/** - * @beta - */ -export interface ConstructableElementRenderer< - T extends ElementRenderer | AsyncElementRenderer = ElementRenderer -> { - new (tagName: string, renderInfo: RenderInfo): T; - - /** - * Tests a constructor to determine if it should be managed by the ElementRenderer. - * @param ctor - The constructor to test. - */ - matchesClass( - ctor: typeof HTMLElement, - tagName: string, - attributes: AttributesMap - ): boolean; -} - -/** - * @beta - */ -export interface ConstructableFASTElementRenderer< - T extends ElementRenderer | AsyncElementRenderer = ElementRenderer -> extends ConstructableElementRenderer { - /** - * Prevents this ElementRenderer from matching an element type. - * @param elements - The elements to disable rendering for. - * - * @remarks - * Elements can be disabled by tag-name, constructor, or FASTElementDefinition. - */ - disable(...args: Array): void; -} - -/** - * @internal - */ -export type AttributesMap = Map; diff --git a/packages/fast-ssr/src/escape-html.ts b/packages/fast-ssr/src/escape-html.ts deleted file mode 100644 index 8b1cb954714..00000000000 --- a/packages/fast-ssr/src/escape-html.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * This file was ported from {@link https://github.com/lit/lit/tree/main/packages/labs/ssr}. - * Please see {@link ../ACKNOWLEDGEMENTS.md} - */ - -const replacements = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - // Note ' was not defined in the HTML4 spec, and is not supported by very - // old browsers like IE8, so a codepoint entity is used instead. - "'": "'", -}; - -/** - * Replaces characters which have special meaning in HTML (&<>"') with escaped - * HTML entities ("&", "<", etc.). - */ -export const escapeHtml = (str: string) => - str.replace(/[&<>"']/g, char => replacements[char as keyof typeof replacements]); diff --git a/packages/fast-ssr/src/event-utilities.ts b/packages/fast-ssr/src/event-utilities.ts deleted file mode 100644 index 2719a0a5379..00000000000 --- a/packages/fast-ssr/src/event-utilities.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function shouldBubble(event: Event) { - return event.bubbles && !event.cancelBubble; -} diff --git a/packages/fast-ssr/src/exports.spec.ts b/packages/fast-ssr/src/exports.spec.ts deleted file mode 100644 index e4c45cea7e2..00000000000 --- a/packages/fast-ssr/src/exports.spec.ts +++ /dev/null @@ -1,87 +0,0 @@ -import "./install-dom-shim.js"; - -import { strictEqual } from "node:assert/strict"; -import { describe, test } from "node:test"; -import { FASTElement, html, HTMLDirective, ref, RefDirective, StatelessAttachedAttributeDirective, ViewController } from "@microsoft/fast-element"; -import { uniqueElementName } from "@microsoft/fast-element/testing.js"; -import fastSSR from "./exports.js"; -import { ViewBehaviorFactoryRenderer } from "./template-renderer/directives.js"; -import { consolidate } from "./test-utilities/consolidate.js"; - -describe("fastSSR default export", () => { - test("should return a TemplateRenderer configured to create a RenderInfo object using the returned ElementRenderer", () => { - const { templateRenderer, ElementRenderer } = fastSSR(); - strictEqual(templateRenderer.createRenderInfo().elementRenderers.includes(ElementRenderer), true) - }) - - test("should render FAST elements without the `defer-hydration` attribute by default", () => { - const { templateRenderer } = fastSSR(); - const name = uniqueElementName(); - FASTElement.define(name); - - strictEqual(consolidate(templateRenderer.render(`<${name}>`)), - `<${name}>` - ); - }); - test("should render FAST elements with the `defer-hydration` attribute when deferHydration is configured to be true", () => { - const { templateRenderer } = fastSSR({ deferHydration: true }); - const name = uniqueElementName(); - FASTElement.define(name); - - strictEqual(consolidate(templateRenderer.render(`<${name}>`)), - `<${name} defer-hydration>` - ) - }); - test("should not render FAST elements with the `defer-hydration` attribute when deferHydration is configured to be false", () => { - const { templateRenderer } = fastSSR({ deferHydration: false }); - const name = uniqueElementName(); - FASTElement.define(name); - - strictEqual(consolidate(templateRenderer.render(`<${name}>`)), - `<${name}>` - ) - }); - - test("should render a custom directive using a registered ViewBehaviorFactoryRenderer", () => { - class Directive extends StatelessAttachedAttributeDirective { - bind(controller: ViewController) {} - constructor(public readonly value: string) { - super(value); - } - } - - HTMLDirective.define(Directive); - - const renderer: ViewBehaviorFactoryRenderer = { - matcher: Directive, - *render(behaviorFactory, renderInfo, source, renderer, context) { - yield `value='${behaviorFactory.value}'`; - }, - } - - const { templateRenderer } = fastSSR({viewBehaviorFactoryRenderers: [renderer]}) - strictEqual(consolidate(templateRenderer.render(html`

    `)), - `

    ` - ) - }); - test("should support overriding pre-registered ViewBehaviorFactoryRenderer", () => { - class Directive extends StatelessAttachedAttributeDirective { - bind(controller: ViewController) {} - constructor(public readonly value: string) { - super(value); - } - } - - const renderer: ViewBehaviorFactoryRenderer = { - matcher: RefDirective, - *render(behaviorFactory, renderInfo, source, renderer, context) { - yield `ref='some-ref'`; - }, - } - - const { templateRenderer } = fastSSR({viewBehaviorFactoryRenderers: [renderer]}) - strictEqual(consolidate(templateRenderer.render(html`

    `)), - `

    ` - ) - }); -}); diff --git a/packages/fast-ssr/src/exports.ts b/packages/fast-ssr/src/exports.ts deleted file mode 100644 index 990a42d6740..00000000000 --- a/packages/fast-ssr/src/exports.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { FASTElement, FASTElementDefinition } from "@microsoft/fast-element"; -import { - AsyncFASTElementRenderer, - SyncFASTElementRenderer, -} from "./element-renderer/fast-element-renderer.js"; -import { - AsyncElementRenderer, - AttributesMap, - ConstructableElementRenderer, - ConstructableFASTElementRenderer, - ElementRenderer, -} from "./element-renderer/interfaces.js"; -import { RenderInfo } from "./render-info.js"; -import { StyleElementStyleRenderer, StyleRenderer } from "./styles/style-renderer.js"; -import { - defaultViewBehaviorFactoryRenderers, - ViewBehaviorFactoryRenderer, -} from "./template-renderer/directives.js"; -import { - AsyncTemplateRenderer, - DefaultTemplateRenderer, - TemplateRenderer, -} from "./template-renderer/template-renderer.js"; - -// Perform necessary configuration of FAST-Element library -// for rendering in NodeJS -import "./configure-fast-element.js"; - -/** - * Configuration for SSR factory. - * @beta - */ -export interface SSRConfiguration { - /** - * When 'async', configures the renderer to support async rendering. - * 'async' rendering will yield 'string | Promise' - * - * Defaults to 'sync'. - */ - renderMode?: "sync" | "async"; - - /** - * Configures the renderer to yield the `defer-hydration` attribute during element rendering. - * Can be a boolean or a function that receives tagName and returns a boolean. - * The `defer-hydration` attribute can be used to prevent immediate hydration of the element - * by fast-element by importing hydration support in the client bundle. - * - * Defaults to `false` - * @example - * - * ```ts - * import "@microsoft/fast-element/install-element-hydration"; - * ``` - */ - deferHydration?: boolean | ((tagName: string) => boolean); - - /** - * Configures the renderer to emit markup that allows fast-element to hydrate elements. - * - * Defaults to `false` - */ - emitHydratableMarkup?: boolean; - - /** - * Renderers for author-defined ViewBehaviorFactories. - */ - viewBehaviorFactoryRenderers?: ViewBehaviorFactoryRenderer[]; - - /** - * When true or when a error handler is provided, the renderer will - * attempt to recover from errors that occur at specific points, - * during rendering, including: - * - * connectedCallback(): No declarative shadow-dom will be emitted for the element - */ - tryRecoverFromError?: boolean | ((e: unknown) => void); - - /** - * Optional custom style renderer instance, used to override StyleElementStyleRenderer - */ - styleRenderer?: StyleRenderer; -} - -/** @beta */ -function fastSSR(): { - templateRenderer: TemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; -/** @beta */ -function fastSSR(config: Omit): { - templateRenderer: TemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; -/** @beta */ -function fastSSR(config: SSRConfiguration & Record<"renderMode", "sync">): { - templateRenderer: TemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; -/** @beta */ -function fastSSR(config: SSRConfiguration & Record<"renderMode", "async">): { - templateRenderer: AsyncTemplateRenderer; - ElementRenderer: ConstructableFASTElementRenderer; -}; - -/** - * Factory for creating SSR rendering assets. - * @example - * ```ts - * import "@microsoft/install-dom-shim"; - * import fastSSR from "@microsoft/fast-ssr"; - * import { html } from "@microsoft/fast-element"; - * const { templateRenderer } = fastSSR(); - * - * const streamableSSRResult = templateRenderer.render(html`...`); - * ``` - * - * @beta - */ -function fastSSR(config?: SSRConfiguration): any { - const rConfig: Required = { - renderMode: "sync", - deferHydration: false, - emitHydratableMarkup: false, - tryRecoverFromError: false, - ...config, - } as Required; - const templateRenderer = new DefaultTemplateRenderer(); - const deferHydration = - typeof rConfig.deferHydration === "function" - ? rConfig.deferHydration - : () => !!rConfig?.deferHydration; - templateRenderer.deferHydration = deferHydration; - templateRenderer.emitHydratableMarkup = !!rConfig.emitHydratableMarkup; - templateRenderer.tryRecoverFromErrors = rConfig.tryRecoverFromError; - - const elementRenderer = class extends (rConfig.renderMode !== "async" - ? SyncFASTElementRenderer - : AsyncFASTElementRenderer) { - static #disabledConstructors = new Set(); - - public static matchesClass( - ctor: typeof HTMLElement, - tagName: string, - attributes: AttributesMap - ): boolean { - if (FASTElementDefinition.getByType(ctor) === undefined) { - return false; - } - - const disabled = elementRenderer.#disabledConstructors; - - return !(disabled.has(tagName) || disabled.has(ctor)); - } - - public static disable( - ...elements: Array - ) { - for (const element of elements) { - elementRenderer.#disabledConstructors.add( - element instanceof FASTElementDefinition ? element.type : element - ); - } - } - protected templateRenderer: DefaultTemplateRenderer = templateRenderer; - protected styleRenderer = - rConfig.styleRenderer || new StyleElementStyleRenderer(); - protected deferHydration = deferHydration; - }; - - templateRenderer.withDefaultElementRenderers( - elementRenderer as unknown as ConstructableElementRenderer - ); - - // Configure out-of-box ViewBehaviorFactory renderers first - templateRenderer.withViewBehaviorFactoryRenderers( - ...defaultViewBehaviorFactoryRenderers - ); - - // Add any author-defined ViewBehaviorFactories. This order allows overriding - // out-of-box renderers. - if (Array.isArray(rConfig.viewBehaviorFactoryRenderers)) { - templateRenderer.withViewBehaviorFactoryRenderers( - ...rConfig.viewBehaviorFactoryRenderers - ); - } - - return { - templateRenderer, - ElementRenderer: elementRenderer, - }; -} - -export default fastSSR; -export * from "./declarative-shadow-dom-polyfill.js"; -export * from "./request-storage.js"; -export { templateCacheController } from "./template-parser/template-parser.js"; -export type { - ElementRenderer, - AsyncElementRenderer, - StyleRenderer, - TemplateRenderer, - AsyncTemplateRenderer, - ViewBehaviorFactoryRenderer, - RenderInfo, - ConstructableElementRenderer, - ConstructableFASTElementRenderer, -}; diff --git a/packages/fast-ssr/src/fast-command-buffer/index.fixture.html b/packages/fast-ssr/src/fast-command-buffer/index.fixture.html deleted file mode 100644 index fbfb1bcc383..00000000000 --- a/packages/fast-ssr/src/fast-command-buffer/index.fixture.html +++ /dev/null @@ -1,301 +0,0 @@ - - - - - - - - - - - -
    - - - - - - - -
    -
    - - - - - diff --git a/packages/fast-ssr/src/fast-command-buffer/index.ts b/packages/fast-ssr/src/fast-command-buffer/index.ts deleted file mode 100644 index a44beeb69f1..00000000000 --- a/packages/fast-ssr/src/fast-command-buffer/index.ts +++ /dev/null @@ -1,149 +0,0 @@ -const FASTCommandBufferAttributeName: string = "data-fast-buffer-events"; - -interface CommandCache { - originalNode: HTMLElement; - event: Event; - attachedNode: HTMLElement | null; -} - -/** - * Component for recording user events on SSR rendered FAST components which have not yet hydrated and replaying those - * events when they have. - * During SSR an instance of the component should be placed as a direct child within every template - * that contains children with behaviors bound to user generated events (click, mouseover, focus, etc). When those child element - * tags are rendered FASTCommandBufferAttributeName attribute must be included that lists the events which the element needs to - * have recorded as a comma delimited list (i.e.