From 0226d08de6d64d62ff587a3b1cef6a8900b559ba Mon Sep 17 00:00:00 2001 From: Thomas Allmer Date: Mon, 4 Apr 2022 09:06:04 +0200 Subject: [PATCH] feat: add progressive hydration support --- .gitignore | 8 +- config/rocket.config.js | 9 +- examples/blog/config/rocket.config.js | 5 + examples/blog/package.json | 2 +- examples/blog/site/pages/about.rocket.md | 7 + .../site/pages/blog/hello-world.rocket.md | 11 + .../blog/site/pages/blog/with-image.rocket.md | 11 + examples/blog/site/pages/index.rocket.js | 9 + .../pages/pageTreeData.rocketGenerated.json | 44 +- examples/blog/site/pages/recursive.data.js | 11 +- .../landing-spark/config/rocket.config.js | 2 + examples/landing-spark/package.json | 5 +- .../site/pages/index.rocket.html | 11 + .../pages/pageTreeData.rocketGenerated.json | 3 +- .../site/pages/recursive.data.js | 3 +- package.json | 12 +- packages/cli/src/RocketBuild.js | 5 + packages/cli/src/RocketCli.js | 3 + packages/cli/src/RocketStart.js | 2 + packages/cli/test-node/01-config.test.js | 27 + .../config/rocket.config.js | 4 + .../site/package.json | 7 + .../site/pages/index.rocket.js | 14 + .../site/pages/local.data.js | 9 + .../pages/pageTreeData.rocketGenerated.json | 13 + .../site/src/MyVeryLongElementName.js | 29 + packages/cli/types/main.d.ts | 3 + packages/components/dialog/RocketDialog.js | 20 + packages/components/package.json | 8 + packages/components/src/index.components.js | 24 +- packages/components/src/pageDefaults.js | 7 + packages/drawer/package.json | 2 +- packages/engine/package.json | 8 + packages/engine/src/Engine.js | 77 ++- packages/engine/src/Watcher.js | 3 +- .../src/dev-server/devServerRegisterTab.js | 17 +- .../engine/src/file-header/RocketHeader.js | 565 ++++++++++++++++++ .../src/file-header/updateRocketHeader.js | 206 ------- .../validateComponentImportString.js | 12 + .../engine/src/helpers/findJsDependencies.js | 10 +- packages/engine/src/helpers/transformFile.js | 10 +- .../engine/src/hydration/HydrationLoader.js | 276 +++++++++ packages/engine/src/hydration/evaluate.js | 52 ++ .../engine/src/hydration/extractStrategies.js | 86 +++ packages/engine/src/index.hydration.js | 1 + .../src/transformers/InjectLoaderFile.js | 34 ++ packages/engine/src/web-menu/PageTree.js | 5 +- packages/engine/src/worker/importViaWorker.js | 4 +- packages/engine/src/worker/importWorker.js | 5 +- packages/engine/src/worker/renderViaWorker.js | 12 +- packages/engine/src/worker/renderWorker.js | 70 ++- .../engine/test-node/12-playwright.spec.js | 4 +- packages/engine/test-node/13-config.test.js | 35 ++ .../engine/test-node/14-components.test.js | 23 - .../14a-components-stategies.test.js | 259 ++++++++ .../test-node/14b-components-files.test.js | 487 +++++++++++++++ .../test-node/14c-components-e2e.spec.js | 189 ++++++ .../docs/pageTreeData.rocketGenerated.json | 10 + .../docs/pageTreeData.rocketGenerated.json | 3 +- .../03-long-file-header-comment/package.json | 7 + .../pages/index.rocket.js | 17 + .../pages/local.data.js | 9 + .../pages/pageTreeData.rocketGenerated.json | 13 + .../src/MyVeryLongElementName.js | 29 + .../01-load-server-side/docs/index.rocket.js | 11 + .../01-load-server-side/docs/index.rocket.md | 9 - .../docs/pageTreeData.rocketGenerated.json | 6 +- .../docs/recursive.data.js | 4 +- .../01-load-server-side/package.json | 7 + .../02-register-hydrate/docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 5 + .../02-register-hydrate/package.json | 7 + .../02-register-hydrate/src/MyEl.js | 7 + .../03-register-client/docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../03-register-client/docs/recursive.data.js | 5 + .../03-register-client/package.json | 7 + .../03-register-client/src/MyEl2.js | 7 + .../docs/index.rocket.js | 16 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 6 + .../04-hydration-and-client/package.json | 7 + .../04-hydration-and-client/src/MyEl4.js | 7 + .../04-hydration-and-client/src/MyOnly.js | 7 + .../docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 5 + .../package.json | 7 + .../src/MyEl.js | 7 + .../docs/index.rocket.md | 13 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 5 + .../package.json | 7 + .../src/MyEl.js | 7 + .../docs/index.rocket.js | 7 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 5 + .../07-removes-registrations/package.json | 7 + .../pageTreeData.rocketGenerated.json | 8 + .../07-removes-registrations/src/MyEl.js | 7 + .../docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 21 + .../package.json | 7 + .../pageTreeData.rocketGenerated.json | 8 + .../src/MyEl.js | 7 + .../docs/index.rocket.js | 13 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 22 + .../package.json | 7 + .../pageTreeData.rocketGenerated.json | 8 + .../src/MyEl.js | 7 + .../src/NextEl.js | 7 + .../src/OtherEl.js | 7 + .../src/index.js | 2 + .../docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 5 + .../package.json | 7 + .../10-start-inject-remove-loader/src/MyEl.js | 7 + .../docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 10 + .../docs/recursive.data.js | 5 + .../package.json | 7 + .../11-start-correct-wrong-header/src/MyEl.js | 7 + .../docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 8 + .../docs/recursive.data.js | 5 + .../package.json | 7 + .../12-build-correct-wrong-header/src/MyEl.js | 7 + .../docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 11 + .../docs/recursive.data.js | 15 + .../50-hydration-onClientLoad/package.json | 7 + .../50-hydration-onClientLoad/src/MyEl.js | 22 + .../51-hydration-onClick/docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 11 + .../docs/recursive.data.js | 15 + .../51-hydration-onClick/package.json | 7 + .../51-hydration-onClick/src/MyEl.js | 29 + .../docs/index.rocket.js | 14 + .../docs/pageTreeData.rocketGenerated.json | 11 + .../docs/recursive.data.js | 15 + .../52-hydration-onVisible/package.json | 7 + .../52-hydration-onVisible/src/MyEl.js | 29 + .../53-hydration-onMedia/docs/index.rocket.js | 11 + .../docs/pageTreeData.rocketGenerated.json | 11 + .../docs/recursive.data.js | 15 + .../53-hydration-onMedia/package.json | 7 + .../53-hydration-onMedia/src/MyEl.js | 29 + .../docs/index.rocket.js | 13 + .../docs/pageTreeData.rocketGenerated.json | 11 + .../docs/recursive.data.js | 15 + .../54-hydration-onMedia-onClick/package.json | 7 + .../54-hydration-onMedia-onClick/src/MyEl.js | 29 + .../docs/index.rocket.js | 13 + .../docs/pageTreeData.rocketGenerated.json | 11 + .../docs/recursive.data.js | 15 + .../package.json | 7 + .../src/MyEl.js | 29 + packages/engine/test-node/test-helpers.js | 14 +- packages/engine/types/main.d.ts | 38 +- packages/launch/src/LayoutSidebar.js | 29 +- packages/mdjs-preview/package.json | 2 +- packages/search/package.json | 6 +- packages/search/src/RocketCliSearch.js | 2 + packages/search/src/index.components.js | 2 +- patches/@web+dev-server+0.1.29.patch | 12 - patches/@web+dev-server-core+0.3.17.patch | 12 - patches/es-module-lexer+0.9.3.patch | 12 - presets/spark/package.json | 4 + presets/spark/src/index.components.js | 4 +- .../10--setup/10--getting-started.rocket.md | 14 +- .../10--setup/20--adding-pages.rocket.md | 17 +- .../10--setup/30--use-javascript.rocket.md | 14 +- site/pages/10--docs/10--setup/index.rocket.js | 14 +- .../10--project-structure.rocket.md | 17 +- .../10--docs/20--basics/20--pages.rocket.md | 17 +- .../20--basics/30--data-cascade.rocket.md | 14 +- .../20--basics/40--components.rocket.md | 46 +- .../10--docs/20--basics/50--layouts.rocket.md | 17 +- .../10--docs/20--basics/60--routing.rocket.md | 14 +- .../20--basics/70--navigation.rocket.md | 14 +- .../20--basics/80--hydration.rocket.md | 261 +++++++- .../10--docs/20--basics/90--assets.rocket.md | 17 +- .../20--basics/95--configuration.rocket.md | 17 +- .../pages/10--docs/20--basics/index.rocket.js | 14 +- .../30--guides/20--social-media.rocket.md | 14 +- .../10--docs/30--guides/30--images.rocket.md | 17 +- .../30--guides/40--markdown.rocket.md | 14 +- .../10--docs/30--guides/50--go-live.rocket.md | 14 +- .../30--guides/60--cross-browser.rocket.md | 14 +- .../30--guides/70--styles-and-css.rocket.md | 14 +- .../30--guides/80--web-fonts.rocket.md | 14 +- .../30--guides/90--data-fetching.rocket.md | 17 +- .../10--docs/30--guides/95--deploy.rocket.md | 17 +- .../pages/10--docs/30--guides/index.rocket.js | 14 +- site/pages/10--docs/index.rocket.md | 14 +- .../10--components/10--overview.rocket.md | 14 +- .../10--components/card-icon.rocket.md | 17 +- .../10--components/index.rocket.js | 14 +- .../inline-notification.rocket.md | 17 +- .../20--launch/10--overview.rocket.md | 14 +- .../20--launch/20--service-worker.rocket.md | 14 +- .../20--presets/20--launch/index.rocket.js | 14 +- .../30--spark/10--overview.rocket.md | 14 +- .../20--presets/30--spark/20--demo.rocket.js | 27 +- .../20--presets/30--spark/index.rocket.js | 14 +- site/pages/20--presets/index.rocket.md | 14 +- .../10--overview.rocket.md | 14 +- .../10--plugins-manager/index.rocket.js | 14 +- .../10--overview.rocket.md | 14 +- .../20--preview.rocket.md | 17 +- .../30--story.rocket.md | 14 +- .../20--markdown-javascript/index.rocket.js | 14 +- .../30--rollup-config/10--overview.rocket.md | 14 +- .../30--rollup-config/index.rocket.js | 14 +- .../10--overview.rocket.md | 17 +- .../40--check-html-links/index.rocket.js | 14 +- site/pages/30--tools/index.rocket.md | 14 +- ...01--introducing-check-html-links.rocket.md | 14 +- site/pages/40--blog/index.rocket.js | 14 +- site/pages/__shared/search.js | 3 +- site/pages/index.rocket.js | 7 + site/pages/opengraph.rocket.js | 7 + site/pages/pageTreeData.rocketGenerated.json | 30 + site/pages/recursive.data.js | 7 +- site/src/components/MyCounter.js | 41 ++ yarn.lock | 349 +++++------ 230 files changed, 4519 insertions(+), 942 deletions(-) create mode 100644 examples/blog/config/rocket.config.js create mode 100644 packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/config/rocket.config.js create mode 100644 packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/package.json create mode 100644 packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/index.rocket.js create mode 100644 packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/local.data.js create mode 100644 packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/pageTreeData.rocketGenerated.json create mode 100644 packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/src/MyVeryLongElementName.js create mode 100644 packages/components/dialog/RocketDialog.js create mode 100644 packages/engine/src/file-header/RocketHeader.js delete mode 100644 packages/engine/src/file-header/updateRocketHeader.js create mode 100644 packages/engine/src/file-header/validateComponentImportString.js create mode 100644 packages/engine/src/hydration/HydrationLoader.js create mode 100644 packages/engine/src/hydration/evaluate.js create mode 100644 packages/engine/src/hydration/extractStrategies.js create mode 100644 packages/engine/src/index.hydration.js create mode 100644 packages/engine/src/transformers/InjectLoaderFile.js delete mode 100644 packages/engine/test-node/14-components.test.js create mode 100644 packages/engine/test-node/14a-components-stategies.test.js create mode 100644 packages/engine/test-node/14b-components-files.test.js create mode 100644 packages/engine/test-node/14c-components-e2e.spec.js create mode 100644 packages/engine/test-node/fixtures/06-error-handling/01-page-error/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/package.json create mode 100644 packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/local.data.js create mode 100644 packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/src/MyVeryLongElementName.js create mode 100644 packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.js delete mode 100644 packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.md create mode 100644 packages/engine/test-node/fixtures/14-components/01-load-server-side/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/02-register-hydrate/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/02-register-hydrate/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/03-register-client/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/03-register-client/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/03-register-client/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/03-register-client/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/03-register-client/src/MyEl2.js create mode 100644 packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/04-hydration-and-client/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyEl4.js create mode 100644 packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyOnly.js create mode 100644 packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/index.rocket.md create mode 100644 packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/07-removes-registrations/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/07-removes-registrations/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/07-removes-registrations/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/NextEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/OtherEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/index.js create mode 100644 packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/51-hydration-onClick/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/51-hydration-onClick/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/src/MyEl.js create mode 100644 packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/index.rocket.js create mode 100644 packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/pageTreeData.rocketGenerated.json create mode 100644 packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/recursive.data.js create mode 100644 packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/package.json create mode 100644 packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/src/MyEl.js delete mode 100644 patches/@web+dev-server+0.1.29.patch delete mode 100644 patches/@web+dev-server-core+0.3.17.patch delete mode 100644 patches/es-module-lexer+0.9.3.patch create mode 100644 site/src/components/MyCounter.js diff --git a/.gitignore b/.gitignore index 322d9b53..6b35b198 100644 --- a/.gitignore +++ b/.gitignore @@ -29,8 +29,11 @@ stats.html # Rocket Search rocket-search-index.json -## Rocket ignore files (need to be the full relative path to the folders) +## Rocket ignore files *-mdjs-generated.js +*-converted-md-source.js +*-converted-md.js +*-converted-html.js _site _site-dev @@ -41,3 +44,6 @@ _merged_includes __output __output-dev docs_backup + +## Local playground +examples/testing diff --git a/config/rocket.config.js b/config/rocket.config.js index b831bc59..8abc71eb 100644 --- a/config/rocket.config.js +++ b/config/rocket.config.js @@ -31,9 +31,12 @@ export function absoluteBaseUrlNetlify(fallback) { return absoluteBaseUrl; } -/** @type {import('@rocket/cli/types/main').RocketCliOptions} */ -export default { +export default /** @type {import('@rocket/cli/types/main').RocketCliOptions} */ ({ absoluteBaseUrl: absoluteBaseUrlNetlify('http://localhost:8080'), + longFileHeaderWidth: 100, + longFileHeaderComment: '// prettier-ignore', + + // buildOpenGraphImages: false, presets: [ rocketLaunch(), @@ -55,4 +58,4 @@ export default { // pathPrefix: '/_site/', // clearOutputDir: false, -}; +}); diff --git a/examples/blog/config/rocket.config.js b/examples/blog/config/rocket.config.js new file mode 100644 index 00000000..55865a27 --- /dev/null +++ b/examples/blog/config/rocket.config.js @@ -0,0 +1,5 @@ +export default /** @type {import('@rocket/cli').RocketCliOptions} */ ({ + absoluteBaseUrl: 'http://localhost:8080', + longFileHeaderWidth: 100, + longFileHeaderComment: '// prettier-ignore', +}); diff --git a/examples/blog/package.json b/examples/blog/package.json index 6c6b05f7..78e7f65a 100644 --- a/examples/blog/package.json +++ b/examples/blog/package.json @@ -7,7 +7,7 @@ "exports": { ".": "./src/index.js", "./styles/*": "./site/src/styles/*", - "./components/*": "./site/src/components/*" + "./components/*": "./site/src/components/*.js" }, "scripts": { "build": "rocket build", diff --git a/examples/blog/site/pages/about.rocket.md b/examples/blog/site/pages/about.rocket.md index 55d7dffa..7777e86e 100644 --- a/examples/blog/site/pages/about.rocket.md +++ b/examples/blog/site/pages/about.rocket.md @@ -3,6 +3,13 @@ export const sourceRelativeFilePath = 'about.rocket.md'; import { html, layout, components } from './recursive.data.js'; export { html, layout, components }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader)); + // prettier-ignore + customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter)); +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/examples/blog/site/pages/blog/hello-world.rocket.md b/examples/blog/site/pages/blog/hello-world.rocket.md index 42ccb9f3..de290365 100644 --- a/examples/blog/site/pages/blog/hello-world.rocket.md +++ b/examples/blog/site/pages/blog/hello-world.rocket.md @@ -4,6 +4,17 @@ export const sourceRelativeFilePath = 'blog/hello-world.rocket.md'; import { html, components } from '../recursive.data.js'; import { layout } from './local.data.js'; export { html, layout, components }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader)); + // prettier-ignore + customElements.define('blog-author', await import('@example/blog/components/BlogAuthor').then(m => m.BlogAuthor)); + // prettier-ignore + customElements.define('blog-post', await import('@example/blog/components/BlogPost').then(m => m.BlogPost)); + // prettier-ignore + customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter)); +} /* END - Rocket auto generated - do not touch */ export const title = 'Hello world!'; diff --git a/examples/blog/site/pages/blog/with-image.rocket.md b/examples/blog/site/pages/blog/with-image.rocket.md index 1a68c87f..80def70a 100644 --- a/examples/blog/site/pages/blog/with-image.rocket.md +++ b/examples/blog/site/pages/blog/with-image.rocket.md @@ -4,6 +4,17 @@ export const sourceRelativeFilePath = 'blog/with-image.rocket.md'; import { html, components } from '../recursive.data.js'; import { layout } from './local.data.js'; export { html, layout, components }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader)); + // prettier-ignore + customElements.define('blog-author', await import('@example/blog/components/BlogAuthor').then(m => m.BlogAuthor)); + // prettier-ignore + customElements.define('blog-post', await import('@example/blog/components/BlogPost').then(m => m.BlogPost)); + // prettier-ignore + customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter)); +} /* END - Rocket auto generated - do not touch */ export const title = 'With Image!'; diff --git a/examples/blog/site/pages/index.rocket.js b/examples/blog/site/pages/index.rocket.js index b0ce882b..0bc86e00 100644 --- a/examples/blog/site/pages/index.rocket.js +++ b/examples/blog/site/pages/index.rocket.js @@ -2,6 +2,15 @@ export const sourceRelativeFilePath = 'index.rocket.js'; import { html, components } from './recursive.data.js'; export { html, components }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('blog-header', await import('@example/blog/components/BlogHeader').then(m => m.BlogHeader)); + // prettier-ignore + customElements.define('blog-post-preview', await import('@example/blog/components/BlogPostPreview').then(m => m.BlogPostPreview)); + // prettier-ignore + customElements.define('site-footer', await import('@example/blog/components/SiteFooter').then(m => m.SiteFooter)); +} /* END - Rocket auto generated - do not touch */ export const layout = false; diff --git a/examples/blog/site/pages/pageTreeData.rocketGenerated.json b/examples/blog/site/pages/pageTreeData.rocketGenerated.json index 7c1f5ab1..aba62429 100644 --- a/examples/blog/site/pages/pageTreeData.rocketGenerated.json +++ b/examples/blog/site/pages/pageTreeData.rocketGenerated.json @@ -8,8 +8,26 @@ "sourceRelativeFilePath": "index.rocket.js", "level": 0, "description": "The perfect starter for your perfect blog.", + "layout": false, "permalink": "https://example.com/", "children": [ + { + "title": "", + "h1": "\n \n ", + "headlinesWithId": [ + { + "text": "About", + "id": "about", + "level": 1 + } + ], + "name": "\n \n ", + "menuLinkText": "\n \n ", + "url": "/about/", + "outputRelativeFilePath": "about/index.html", + "sourceRelativeFilePath": "about.rocket.md", + "level": 1 + }, { "name": "blog/index.rocket.js", "menuLinkText": "blog/index.rocket.js", @@ -17,6 +35,7 @@ "outputRelativeFilePath": "blog/index.html", "sourceRelativeFilePath": "blog/index.rocket.js", "level": 1, + "layout": false, "children": [ { "title": "Hello world!", @@ -27,11 +46,9 @@ "outputRelativeFilePath": "blog/hello-world/index.html", "sourceRelativeFilePath": "blog/hello-world.rocket.md", "level": 2, - "alt": "", "author": "Thomas Allmer (@daKmoR)", "authorHref": "https://twitter.com/daKmoR", "description": "Just a Hello World Post!", - "heroImage": "", "publishDate": "12 Sep 2021", "value": 128 }, @@ -52,26 +69,7 @@ "publishDate": "13 Sep 2021", "value": 128 } - ], - "layout": false - }, - { - "title": "", - "h1": "\n \n ", - "headlinesWithId": [ - { - "text": "About", - "id": "about", - "level": 1 - } - ], - "name": "\n \n ", - "menuLinkText": "\n \n ", - "url": "/about/", - "outputRelativeFilePath": "about/index.html", - "sourceRelativeFilePath": "about.rocket.md", - "level": 1 + ] } - ], - "layout": false + ] } \ No newline at end of file diff --git a/examples/blog/site/pages/recursive.data.js b/examples/blog/site/pages/recursive.data.js index 14cad84b..d46a29f9 100644 --- a/examples/blog/site/pages/recursive.data.js +++ b/examples/blog/site/pages/recursive.data.js @@ -7,10 +7,9 @@ export { html } from 'lit'; export const layout = new LayoutPage(); export const components = { - 'blog-author': () => import('../src/components/BlogAuthor.js').then(m => m.BlogAuthor), - 'blog-header': () => import('../src/components/BlogHeader.js').then(m => m.BlogHeader), - 'blog-post': () => import('../src/components/BlogPost.js').then(m => m.BlogPost), - 'blog-post-preview': () => - import('../src/components/BlogPostPreview.js').then(m => m.BlogPostPreview), - 'site-footer': () => import('../src/components/SiteFooter.js').then(m => m.SiteFooter), + 'blog-author': '@example/blog/components/BlogAuthor::BlogAuthor', + 'blog-header': '@example/blog/components/BlogHeader::BlogHeader', + 'blog-post': '@example/blog/components/BlogPost::BlogPost', + 'blog-post-preview': '@example/blog/components/BlogPostPreview::BlogPostPreview', + 'site-footer': '@example/blog/components/SiteFooter::SiteFooter', }; diff --git a/examples/landing-spark/config/rocket.config.js b/examples/landing-spark/config/rocket.config.js index 157bfbdf..5395426e 100644 --- a/examples/landing-spark/config/rocket.config.js +++ b/examples/landing-spark/config/rocket.config.js @@ -2,5 +2,7 @@ import { rocketSpark } from '@rocket/spark'; export default /** @type {import('@rocket/cli').RocketCliOptions} */ ({ absoluteBaseUrl: 'http://localhost:8080', + longFileHeaderWidth: 100, + longFileHeaderComment: '// prettier-ignore', presets: [rocketSpark()], }); diff --git a/examples/landing-spark/package.json b/examples/landing-spark/package.json index 611c125c..df998e45 100644 --- a/examples/landing-spark/package.json +++ b/examples/landing-spark/package.json @@ -17,5 +17,8 @@ "@rocket/spark": "^0.1.0-alpha.1", "lit": "^2.0.0" }, - "@rocket/template-name": "Landing Page (Spark Theme)" + "@rocket/template-name": "Landing Page (Spark Theme)", + "imports": { + "#components/*": "./site/src/components/*.js" + } } diff --git a/examples/landing-spark/site/pages/index.rocket.html b/examples/landing-spark/site/pages/index.rocket.html index 4a2a112f..3255fa4c 100644 --- a/examples/landing-spark/site/pages/index.rocket.html +++ b/examples/landing-spark/site/pages/index.rocket.html @@ -3,6 +3,17 @@ export const sourceRelativeFilePath = 'index.rocket.html'; import { pageTree, layout, components } from './recursive.data.js'; export { pageTree, layout, components }; +export async function registerCustomElements() { + // server-only components + customElements.define('block-columns', await import('@rocket/components/components/BlockColumns').then(m => m.BlockColumns)); + customElements.define('card-icon', await import('@rocket/components/components/CardIcon').then(m => m.CardIcon)); + customElements.define('feature-small', await import('@rocket/components/components/FeatureSmall').then(m => m.FeatureSmall)); + customElements.define('block-features', await import('@rocket/spark/components/BlockFeatures').then(m => m.BlockFeatures)); + customElements.define('block-columns-gray', await import('#components/BlockColumnsGray').then(m => m.BlockColumnsGray)); + customElements.define('testimonial-small', await import('@rocket/components/components/TestimonialSmall').then(m => m.TestimonialSmall)); + customElements.define('block-blue', await import('@rocket/spark/components/BlockBlue').then(m => m.BlockBlue)); + customElements.define('the-block', await import('@rocket/components/components/TheBlock').then(m => m.TheBlock)); +} /* END - Rocket auto generated - do not touch */ export const title = 'Rocket Landing Page Template (Theme Spark)'; diff --git a/examples/landing-spark/site/pages/pageTreeData.rocketGenerated.json b/examples/landing-spark/site/pages/pageTreeData.rocketGenerated.json index 12ebfdd9..b88959e3 100644 --- a/examples/landing-spark/site/pages/pageTreeData.rocketGenerated.json +++ b/examples/landing-spark/site/pages/pageTreeData.rocketGenerated.json @@ -6,6 +6,5 @@ "url": "/", "outputRelativeFilePath": "index.html", "sourceRelativeFilePath": "index.rocket.html", - "level": 0, - "keepConvertedFiles": true + "level": 0 } \ No newline at end of file diff --git a/examples/landing-spark/site/pages/recursive.data.js b/examples/landing-spark/site/pages/recursive.data.js index 7527dd40..33cf48de 100644 --- a/examples/landing-spark/site/pages/recursive.data.js +++ b/examples/landing-spark/site/pages/recursive.data.js @@ -16,6 +16,5 @@ export const layout = new LayoutHome({ export const components = { ...rocketComponents, ...sparkComponents, - 'block-columns-gray': () => - import('../src/components/BlockColumnsGray.js').then(m => m.BlockColumnsGray), + 'block-columns-gray': '#components/BlockColumnsGray::BlockColumnsGray', }; diff --git a/package.json b/package.json index ec57a034..9a736f93 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "scripts": { "analyze": "run-s analyze:* format:*", "analyze:analyze": "node scripts/workspaces-scripts-bin.mjs analyze", - "build": "npm run build:packages && NODE_DEBUG=engine:rendering node packages/cli/src/cli.js build", + "build": "npm run build:packages && npm run rocket:build", "build:packages": "node scripts/workspaces-scripts-bin.mjs build:package", "build:site": "run-s analyze:* rocket:build", "changeset": "changeset", @@ -27,13 +27,14 @@ "lint:versions": "node scripts/lint-versions.js", "postinstall": "npm run setup", "release": "changeset publish && yarn format", - "rocket:build": "node packages/cli/src/cli.js build", + "rocket:build": "NODE_DEBUG=engine:rendering node --trace-warnings packages/cli/src/cli.js build", "rocket:upgrade": "node packages/cli/src/cli.js upgrade", "search": "node packages/cli/src/cli.js search", "setup": "npm run setup:ts-configs && npm run setup:patches", "setup:patches": "npx patch-package", "setup:ts-configs": "node scripts/generate-ts-configs.mjs", - "start": "NODE_DEBUG=engine:rendering node --no-warnings --experimental-loader ./packages/engine/src/litCssLoader.js packages/cli/src/cli.js start --open", + "start:experimental": "NODE_DEBUG=engine:rendering node --no-warnings --experimental-loader ./packages/engine/src/litCssLoader.js packages/cli/src/cli.js start --open", + "start": "NODE_DEBUG=engine:rendering node --trace-warnings packages/cli/src/cli.js start --open", "test": "yarn test:node && yarn test:web", "test:integration": "playwright test packages/*/test-node/*.spec.js", "test:node": "yarn test:unit && yarn test:integration", @@ -92,7 +93,7 @@ "rollup-plugin-terser": "^7.0.2", "sinon": "^9.2.3", "ts-node": "^9.1.1", - "typescript": "^4.6.1-rc" + "typescript": "^4.6.3" }, "eslintConfig": { "parser": "@typescript-eslint/parser", @@ -126,7 +127,8 @@ }, "imports": { "#pageTree": "./site/pages/__shared/pageTree.js", - "#assets/*": "./site/src/assets/*" + "#assets/*": "./site/src/assets/*", + "#components/*": "./site/src/components/*.js" }, "lint-staged": { "*.js": [ diff --git a/packages/cli/src/RocketBuild.js b/packages/cli/src/RocketBuild.js index 8071fe76..1d3d5d4e 100755 --- a/packages/cli/src/RocketBuild.js +++ b/packages/cli/src/RocketBuild.js @@ -94,16 +94,21 @@ export class RocketBuild { docsDir: this.cli.options.inputDir, outputDir: this.cli.options.outputDevDir, setupPlugins: this.cli.options.setupEnginePlugins, + longFileHeaderWidth: this.cli.options.longFileHeaderWidth, + longFileHeaderComment: this.cli.options.longFileHeaderComment, renderMode: 'production', clearOutputDir: this.cli.options.clearOutputDir, }); + console.log('Engine building...'); await this.engine.build({ autoStop: this.cli.options.buildAutoStop }); if (this.cli.options.buildOpenGraphImages) { + console.log('Generating Open Graph Images...'); await this.buildOpenGraphImages(); } if (this.cli.options.buildOptimize) { + console.log('Optimize Production Build...'); await productionBuild(this.cli.options); await this.engine.copyPublicFilesTo(this.cli.options.outputDir); } diff --git a/packages/cli/src/RocketCli.js b/packages/cli/src/RocketCli.js index 2674fe27..779e44f5 100644 --- a/packages/cli/src/RocketCli.js +++ b/packages/cli/src/RocketCli.js @@ -43,6 +43,9 @@ export class RocketCli { buildAutoStop: true, buildOpenGraphImages: true, + longFileHeaderWidth: 100, + longFileHeaderComment: '', + adjustBuildOptions: options => options, adjustDevServerOptions: options => options, diff --git a/packages/cli/src/RocketStart.js b/packages/cli/src/RocketStart.js index 8226b53c..47958780 100755 --- a/packages/cli/src/RocketStart.js +++ b/packages/cli/src/RocketStart.js @@ -52,6 +52,8 @@ export class RocketStart { outputDir: this.cli.options.outputDir, setupPlugins: this.cli.options.setupEnginePlugins, open: this.cli.options.open, + longFileHeaderWidth: this.cli.options.longFileHeaderWidth, + longFileHeaderComment: this.cli.options.longFileHeaderComment, clearOutputDir: this.cli.options.clearOutputDir, adjustDevServerOptions: this.cli.options.adjustDevServerOptions, setupDevServerMiddleware: this.cli.options.setupDevServerMiddleware, diff --git a/packages/cli/test-node/01-config.test.js b/packages/cli/test-node/01-config.test.js index ed54af4f..c616c493 100644 --- a/packages/cli/test-node/01-config.test.js +++ b/packages/cli/test-node/01-config.test.js @@ -86,4 +86,31 @@ describe('Config', () => { await cleanup(); }); + + it('05: long file header comments', async () => { + const { build, readSource } = await setupTestCli( + 'fixtures/01-config/05-long-file-header-comment/', + ); + await build(); + + expect(readSource('index.rocket.js', { format: false })).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + '// prettier-ignore', + "import { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components } from './local.data.js';", + '// prettier-ignore', + 'export { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + ' // prettier-ignore', + " customElements.define('my-el', await import('@test/components').then(m => m.MyVeryLongElementName));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + "export default () => '';", + '', + ].join('\n'), + ); + }); }); diff --git a/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/config/rocket.config.js b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/config/rocket.config.js new file mode 100644 index 00000000..1b56dea4 --- /dev/null +++ b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/config/rocket.config.js @@ -0,0 +1,4 @@ +export default /** @type {import('../../../../../types/main.js').RocketCliOptions} */ ({ + longFileHeaderComment: '// prettier-ignore', + longFileHeaderWidth: 100, +}); diff --git a/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/package.json b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/package.json new file mode 100644 index 00000000..8f5eebc6 --- /dev/null +++ b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyVeryLongElementName.js" + } +} diff --git a/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/index.rocket.js b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/index.rocket.js new file mode 100644 index 00000000..59074f62 --- /dev/null +++ b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/index.rocket.js @@ -0,0 +1,14 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +// prettier-ignore +import { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components } from './local.data.js'; +// prettier-ignore +export { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('my-el', await import('@test/components').then(m => m.MyVeryLongElementName)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => ''; diff --git a/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/local.data.js b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/local.data.js new file mode 100644 index 00000000..a04f58a9 --- /dev/null +++ b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/local.data.js @@ -0,0 +1,9 @@ +export const veryLongFileHeaderValue = 1; +export const multipleLongFileHeaderValues = 2; +export const fakeHtml = ''; +export const fakeComponents = ''; +export const fakeLayout = ''; + +export const components = { + 'my-el': '@test/components::MyVeryLongElementName', +}; diff --git a/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/pageTreeData.rocketGenerated.json b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..2e73376b --- /dev/null +++ b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/pages/pageTreeData.rocketGenerated.json @@ -0,0 +1,13 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "fakeComponents": "", + "fakeHtml": "", + "fakeLayout": "", + "multipleLongFileHeaderValues": 2, + "veryLongFileHeaderValue": 1 +} \ No newline at end of file diff --git a/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/src/MyVeryLongElementName.js b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/src/MyVeryLongElementName.js new file mode 100644 index 00000000..5f2fc91d --- /dev/null +++ b/packages/cli/test-node/fixtures/01-config/05-long-file-header-comment/site/src/MyVeryLongElementName.js @@ -0,0 +1,29 @@ +import { LitElement, html, css } from 'lit'; + +export class MyVeryLongElementName extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } + + static styles = css` + :host([hydrated]) { + background: green; + display: block; + } + `; +} diff --git a/packages/cli/types/main.d.ts b/packages/cli/types/main.d.ts index 6bd375f3..ab63c1e7 100644 --- a/packages/cli/types/main.d.ts +++ b/packages/cli/types/main.d.ts @@ -31,6 +31,9 @@ export interface FullRocketCliOptions extends Pick // [key: string]: ImagePreset; // }; + longFileHeaderWidth: number; + longFileHeaderComment: string; + adjustDevServerOptions: (options: DevServerConfig) => DevServerConfig; adjustBuildOptions: (options: any) => any; diff --git a/packages/components/dialog/RocketDialog.js b/packages/components/dialog/RocketDialog.js new file mode 100644 index 00000000..77174cee --- /dev/null +++ b/packages/components/dialog/RocketDialog.js @@ -0,0 +1,20 @@ +import { LitElement, html, css } from 'lit'; + +export class RocketDialog extends LitElement { + render() { + return html` +
+

hey

+ +
+ `; + } + + static styles = [ + css` + :host { + display: block; + } + `, + ]; +} diff --git a/packages/components/package.json b/packages/components/package.json index 5b1db730..a3a4f01a 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -27,6 +27,14 @@ "./components": { "types": "./dist-types/src/index.components.d.ts", "default": "./src/index.components.js" + }, + "./components/*": { + "types": "./dist-types/src/*.d.ts", + "default": "./src/*.js" + }, + "./dialog": { + "types": "./dist-types/dialog/RocketDialog.d.ts", + "default": "./dialog/RocketDialog.js" } }, "scripts": { diff --git a/packages/components/src/index.components.js b/packages/components/src/index.components.js index 660df706..9a883e3a 100644 --- a/packages/components/src/index.components.js +++ b/packages/components/src/index.components.js @@ -1,15 +1,15 @@ export const rocketComponents = { // TODO: add back once https://github.com/lit/lit/issues/2633 is fixed - // 'rotating-text': () => - // import('./RotatingText.js').then(m => m.RotatingText), - 'block-columns': () => import('./BlockColumns.js').then(m => m.BlockColumns), - 'testimonial-small': () => import('./TestimonialSmall.js').then(m => m.TestimonialSmall), - 'feature-small': () => import('./FeatureSmall.js').then(m => m.FeatureSmall), - 'the-block': () => import('./TheBlock.js').then(m => m.TheBlock), - 'inline-notification': () => import('./InlineNotification.js').then(m => m.InlineNotification), - 'permanent-notification': () => - import('./PermanentNotification.js').then(m => m.PermanentNotification), - 'card-icon': () => import('./CardIcon.js').then(m => m.CardIcon), - 'server-icon': () => import('./ServerIcon.js').then(m => m.ServerIcon), - 'opengraph-overview': () => import('./OpenGraphOverview.js').then(m => m.OpenGraphOverview), + // 'rotating-text': '@rocket/components/components/RotatingText::RotatingText', + 'block-columns': '@rocket/components/components/BlockColumns::BlockColumns', + 'testimonial-small': '@rocket/components/components/TestimonialSmall::TestimonialSmall', + 'feature-small': '@rocket/components/components/FeatureSmall::FeatureSmall', + 'the-block': '@rocket/components/components/TheBlock::TheBlock', + 'inline-notification': '@rocket/components/components/InlineNotification::InlineNotification', + 'permanent-notification': + '@rocket/components/components/PermanentNotification::PermanentNotification', + 'card-icon': '@rocket/components/components/CardIcon::CardIcon', + 'server-icon': '@rocket/components/components/ServerIcon::ServerIcon', + 'opengraph-overview': '@rocket/components/components/OpenGraphOverview::OpenGraphOverview', + 'rocket-dialog': '@rocket/components/dialog::RocketDialog', }; diff --git a/packages/components/src/pageDefaults.js b/packages/components/src/pageDefaults.js index 54e4a7d9..140fb806 100644 --- a/packages/components/src/pageDefaults.js +++ b/packages/components/src/pageDefaults.js @@ -49,6 +49,13 @@ export function defaultHead({ pageTree, titleWrapperFn, description, siteName }) display: none; } + `, }; } diff --git a/packages/drawer/package.json b/packages/drawer/package.json index adfa556d..66f6307f 100644 --- a/packages/drawer/package.json +++ b/packages/drawer/package.json @@ -38,7 +38,7 @@ "testing" ], "dependencies": { - "@lion/overlays": "^0.29.1", + "@lion/overlays": "^0.32.0", "lit": "^2.0.0" }, "types": "dist-types/index.d.ts" diff --git a/packages/engine/package.json b/packages/engine/package.json index 941b0be5..0cfac333 100644 --- a/packages/engine/package.json +++ b/packages/engine/package.json @@ -24,12 +24,17 @@ "types": "./dist-types/src/index.server.d.ts", "default": "./src/index.server.js" }, + "./hydration": { + "types": "./dist-types/src/index.hydration.d.ts", + "default": "./src/index.hydration.js" + }, "./assets/*": { "default": "./assets/*" } }, "scripts": { "debug": "DEBUG=engine:rendering yarn test", + "debug:integration": "PWDEBUG=1 yarn test:integration", "test": "mocha --require ../../scripts/testMochaGlobalHooks.js --timeout 5000 test-node/**/*.test.{js,cjs} test-node/*.test.{js,cjs}", "test:integration": "playwright test test-node/*.spec.js", "test:watch": "onchange 'src/**/*.{js,cjs}' 'test-node/**/*.{js,cjs}' -- npm test", @@ -59,6 +64,9 @@ ], "server": [ "./dist-types/src/index.server.d.ts" + ], + "hydration": [ + "./dist-types/src/index.hydration.d.ts" ] } } diff --git a/packages/engine/src/Engine.js b/packages/engine/src/Engine.js index 9ee51060..7b58e2d1 100644 --- a/packages/engine/src/Engine.js +++ b/packages/engine/src/Engine.js @@ -5,7 +5,7 @@ /** @typedef {import('../types/main.js').DevServerMiddleware} DevServerMiddleware */ import { existsSync } from 'fs'; -// TODO: implement copy without extra dependency +// TODO: implement copy without extra dependency => node 16.7.0 copy has recursive import fse from 'fs-extra'; import { mkdir, rm } from 'fs/promises'; import path from 'path'; @@ -17,7 +17,6 @@ import { applyPlugins } from 'plugins-manager'; import { gatherFiles } from './gatherFiles.js'; import { cleanupRenderWorker, renderViaWorker } from './worker/renderViaWorker.js'; -import { updateRocketHeader } from './file-header/updateRocketHeader.js'; import { Watcher } from './Watcher.js'; import { PageTree } from './web-menu/PageTree.js'; @@ -29,17 +28,26 @@ import { cleanupAutoGeneratedFiles } from './formats/cleanupAutoGeneratedFiles.j import { cleanupImportWorker } from './worker/importViaWorker.js'; import { devServerRegisterTab } from './dev-server/devServerRegisterTab.js'; import { devServerAdjustAssetUrls } from './dev-server/devServerAdjustAssetUrls.js'; +import { RocketHeader } from './file-header/RocketHeader.js'; const logRendering = debuglog('engine:rendering'); export class Engine { - /** @type {Partial} */ + /** @type {EngineOptions} */ options = { defaultPlugins: [], setupPlugins: [], renderMode: 'development', open: false, + docsDir: '', + outputDir: '', + watchDir: '', clearOutputDir: true, + longFileHeaderWidth: 100, + longFileHeaderComment: '', + devServerPlugins: [], + setupDevServerPlugins: [], + setupDevServerMiddleware: [], }; events = new EventEmitter(); @@ -48,6 +56,12 @@ export class Engine { outputDir = path.join(process.cwd(), '_site-dev'); watchDir = process.cwd(); + _rocketHeaderDefaults = { + inputDir: '', + longFileHeaderWidth: 0, + longFileHeaderComment: '', + }; + /** * @param {Partial} [options] */ @@ -76,6 +90,12 @@ export class Engine { ? path.resolve(userOutputDir) : path.join(this.docsDir, '..', '_site-dev'); this.watchDir = userWatchDir ? path.resolve(userWatchDir) : process.cwd(); + + this._rocketHeaderDefaults = { + inputDir: this.docsDir, + longFileHeaderWidth: this.options.longFileHeaderWidth, + longFileHeaderComment: this.options.longFileHeaderComment, + }; } async build({ autoStop = true } = {}) { @@ -87,8 +107,9 @@ export class Engine { if (sourceFiles.length > 0) { for (const sourceFilePath of sourceFiles) { - await updateRocketHeader(sourceFilePath, this.docsDir); - const result = await this.renderFile(sourceFilePath); + const rocketHeader = new RocketHeader({ sourceFilePath, ...this._rocketHeaderDefaults }); + await rocketHeader.syncDataCascade(); + const result = await this.renderFile({ sourceFilePath, rocketHeader }); await pageTree.add(result.sourceRelativeFilePath); await cleanupAutoGeneratedFiles(result); } @@ -96,7 +117,7 @@ export class Engine { if (pageTree.pageTreeChangedOnSave) { for (const sourceFilePath of sourceFiles) { - const result = await this.renderFile(sourceFilePath); + const result = await this.renderFile({ sourceFilePath, throwOnError: true }); await cleanupAutoGeneratedFiles(result); } } @@ -167,6 +188,7 @@ export class Engine { pageTree, renderFile: this.renderFile.bind(this), renderAllOpenedFiles: this.renderAllOpenedFiles.bind(this), + _rocketHeaderDefaults: this._rocketHeaderDefaults, }, }, { @@ -280,9 +302,10 @@ export class Engine { onPageSavedOrOpenedTabAndServerDependencyChanged: /** @param {{ sourceFilePath: string }} options */ async ({ sourceFilePath }) => { - await updateRocketHeader(sourceFilePath, this.docsDir); + const rocketHeader = new RocketHeader({ sourceFilePath, ...this._rocketHeaderDefaults }); + await rocketHeader.syncDataCascade(); try { - const result = await this.renderFile(sourceFilePath); + const result = await this.renderFile({ sourceFilePath, rocketHeader }); const sourceRelativeFilePath = path.relative(this.docsDir, sourceFilePath); await pageTree.add(sourceRelativeFilePath); await pageTree.save(); @@ -290,7 +313,7 @@ export class Engine { if (pageTree.needsAnotherRenderingPass) { logRendering(`${sourceRelativeFilePath} again as the pageTree was modified.`); - const result = await this.renderFile(sourceFilePath); + const result = await this.renderFile({ sourceFilePath }); await cleanupAutoGeneratedFiles(result); await this.renderAllOpenedFiles({ triggerSourceFilePath: sourceFilePath }); pageTree.needsAnotherRenderingPass = false; @@ -303,7 +326,8 @@ export class Engine { onPageServerDependencySaved: /** @param {{ sourceFilePath: string }} options */ async ({ sourceFilePath }) => { - await updateRocketHeader(sourceFilePath, this.docsDir); + const rocketHeader = new RocketHeader({ sourceFilePath, ...this._rocketHeaderDefaults }); + await rocketHeader.syncDataCascade(); // no need to render as the page itself is not saved nor is the page open in any browser tab // we however clear the current output file as it's now out of date and will be rerendered on demand await this.deleteOutputOf(sourceFilePath); @@ -381,7 +405,7 @@ export class Engine { )} because it is opened in a browser tab and the page tree has changed.`, ); try { - const result = await this.renderFile(sourceFilePath); + const result = await this.renderFile({ sourceFilePath }); await cleanupAutoGeneratedFiles(result); } catch (error) { // nothing already shown in the browser @@ -395,16 +419,39 @@ export class Engine { } /** - * @param {string} sourceFilePath + * @param {object} options + * @param {string} options.sourceFilePath + * @param {import('./file-header/RocketHeader.js').RocketHeader} [options.rocketHeader] + * @param {boolean} [options.throwOnError] * @returns {Promise} */ - async renderFile(sourceFilePath) { - const result = await renderViaWorker({ + async renderFile({ sourceFilePath, rocketHeader, throwOnError = false }) { + const renderOptions = { sourceFilePath, inputDir: this.docsDir, outputDir: this.outputDir, renderMode: this.options.renderMode || 'development', - }); + needsLoader: rocketHeader ? rocketHeader.needsLoader : false, + throwOnError, + }; + let result = await renderViaWorker(renderOptions); + + if (rocketHeader) { + const { needsAnotherRenderingPass } = await rocketHeader.syncComponents({ + outputFileContent: result.fileContent, + outputFilePath: result.outputFilePath, + componentStrings: result.componentStrings, + openGraphHtml: result.openGraphHtml, + }); + if (needsAnotherRenderingPass) { + renderOptions.needsLoader = rocketHeader.needsLoader; + renderOptions.throwOnError = true; + result = await renderViaWorker(renderOptions); + } else if (result.passOnError) { + throw result.passOnError; + } + } + return result; } } diff --git a/packages/engine/src/Watcher.js b/packages/engine/src/Watcher.js index 14f9b53e..a8083e3b 100644 --- a/packages/engine/src/Watcher.js +++ b/packages/engine/src/Watcher.js @@ -117,7 +117,8 @@ export class Watcher { event.path.endsWith('-converted-md-source.js') || event.path.endsWith('-converted-md.js') || event.path.endsWith('-converted-html.js') || - event.path.endsWith('-mdjs-generated.js') + event.path.endsWith('-mdjs-generated.js') || + event.path.endsWith('-loader-generated.js') ) { // file is either in queue or is the pageTreeData.rocketGenerated.json file } else { diff --git a/packages/engine/src/dev-server/devServerRegisterTab.js b/packages/engine/src/dev-server/devServerRegisterTab.js index 26797fc6..312ea446 100644 --- a/packages/engine/src/dev-server/devServerRegisterTab.js +++ b/packages/engine/src/dev-server/devServerRegisterTab.js @@ -1,7 +1,8 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ import { existsSync } from 'fs'; import path from 'path'; import { debuglog } from 'util'; -import { updateRocketHeader } from '../file-header/updateRocketHeader.js'; +import { RocketHeader } from '../file-header/RocketHeader.js'; import { cleanupAutoGeneratedFiles } from '../formats/cleanupAutoGeneratedFiles.js'; const logRendering = debuglog('engine:rendering'); @@ -12,8 +13,9 @@ const logRendering = debuglog('engine:rendering'); * @param {(sourceFilePath: string) => string} options.getSourceFilePathFromUrl * @param {(sourceFilePath: string) => string} options.getOutputFilePath * @param {import('../web-menu/PageTree.js').PageTree} options.pageTree - * @param {(sourceFilePath: string) => Promise} options.renderFile + * @param {(options: { sourceFilePath: String; rocketHeader?: RocketHeader; throwOnError?: boolean }) => Promise} options.renderFile * @param {(options?: { triggerSourceFilePath?: string, deleteOtherFiles?: boolean}) => void} options.renderAllOpenedFiles + * @param {{ inputDir: string; longFileHeaderWidth: number; longFileHeaderComment: string; }} options._rocketHeaderDefaults * @returns {import('../../types/main.js').DevServerPlugin} */ export function devServerRegisterTab({ @@ -23,6 +25,7 @@ export function devServerRegisterTab({ pageTree, renderFile, renderAllOpenedFiles, + _rocketHeaderDefaults, }) { return { name: 'register-tab-plugin', @@ -41,16 +44,20 @@ export function devServerRegisterTab({ const outputFilePath = getOutputFilePath(sourceFilePath); if (!existsSync(outputFilePath)) { const sourceRelativeFilePath = path.relative(inputDir, sourceFilePath); - await updateRocketHeader(sourceFilePath, inputDir); + const rocketHeader = new RocketHeader({ + sourceFilePath, + ..._rocketHeaderDefaults, + }); + await rocketHeader.syncDataCascade(); logRendering(`${sourceRelativeFilePath} because it got requested by a browser tab.`); try { - const result = await renderFile(sourceFilePath); + const result = await renderFile({ sourceFilePath, rocketHeader }); await pageTree.add(sourceRelativeFilePath); await pageTree.save(); await cleanupAutoGeneratedFiles(result); if (pageTree.needsAnotherRenderingPass) { logRendering(`${sourceRelativeFilePath} again as the pageTree was modified.`); - const result = await renderFile(sourceFilePath); + const result = await renderFile({ sourceFilePath }); await cleanupAutoGeneratedFiles(result); await renderAllOpenedFiles({ triggerSourceFilePath: sourceFilePath }); pageTree.needsAnotherRenderingPass = false; diff --git a/packages/engine/src/file-header/RocketHeader.js b/packages/engine/src/file-header/RocketHeader.js new file mode 100644 index 00000000..b4362d5f --- /dev/null +++ b/packages/engine/src/file-header/RocketHeader.js @@ -0,0 +1,565 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { existsSync } from 'fs'; +import { readFile, writeFile } from 'fs/promises'; +import path from 'path'; +import { getAttribute } from '../web-menu/sax-helpers.js'; + +import { parse } from '../helpers/es-module-lexer.js'; +import { getServerCodeFromMd } from '../formats/getServerCodeFromMd.js'; +import { getServerCodeFromHtml } from '../formats/html.js'; +import { importsToImportNames } from './import-names.js'; + +/** @typedef {import('sax-wasm').Text} Text */ +/** @typedef {import('sax-wasm').Tag} Tag */ +/** @typedef {import('sax-wasm').Position} Position */ +/** @typedef {import('../../types/menu.js').Page} Page */ +/** @typedef {import('../../types/main.js').ComponentStrings} ComponentStrings */ + +/** @typedef {{ [tagName: string]: { strategy: string; importString: string }}} ComponentsWithStrategy */ + +import { parser, SaxEventType } from '../web-menu/sax-parser.js'; + +/** + * @param {string} string + * @returns {string} + */ +function capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +/** + * @param {object} options + * @param {string} options.outputFileContent + * @param {ComponentStrings} options.componentStrings + * @returns {ComponentsWithStrategy} + */ +export function getComponentsWithStrategy({ outputFileContent, componentStrings }) { + if (!componentStrings) { + return {}; + } + + /** @type {ComponentsWithStrategy} */ + const componentsWithStrategy = {}; + + parser.eventHandler = (ev, _data) => { + if (ev === SaxEventType.CloseTag) { + const data = /** @type {Tag} */ (/** @type {any} */ (_data)); + const tagName = data.name; + if (tagName.includes('-')) { + const fullStrategy = getAttribute(data, 'loading'); + + if (componentStrings[tagName]) { + if (!componentsWithStrategy[tagName]) { + componentsWithStrategy[tagName] = { + strategy: 'server', + importString: componentStrings[tagName], + }; + } + if (fullStrategy === 'client') { + componentsWithStrategy[tagName].strategy = 'client'; + } + if ( + fullStrategy?.startsWith('hydrate') && + componentsWithStrategy[tagName].strategy !== 'client' + ) { + componentsWithStrategy[tagName].strategy = 'hydrate'; + } + } + } + } + }; + + parser.write(Buffer.from(outputFileContent)); + parser.end(); + + return componentsWithStrategy; +} + +export class RocketHeader { + /** @type {String[]} */ + dataCascade = []; + /** @type {String[]} */ + componentDefinitions = []; + sourceFileContent = ''; + needsLoader = false; + + /** + * + * @param {Object} options + * @param {String} options.sourceFilePath + * @param {String} options.inputDir + * @param {number} options.longFileHeaderWidth + * @param {String} options.longFileHeaderComment + */ + constructor({ sourceFilePath, inputDir, longFileHeaderWidth, longFileHeaderComment }) { + this.sourceFilePath = sourceFilePath; + this.inputDir = inputDir; + this.longFileHeaderWidth = longFileHeaderWidth; + this.longFileHeaderComment = longFileHeaderComment; + } + + /** + * @param {string} sourceFileContent + */ + setSourceFileContent(sourceFileContent) { + this.sourceFileContent = sourceFileContent; + + const dataCascade = []; + const componentDefinitions = []; + + let captureDataCascade = false; + let captureComponents = false; + const lines = this.sourceFileContent.split('\n'); + for (const line of lines) { + if (line.trim() === '/* END - Rocket auto generated - do not touch */') { + break; + } + if (line.trim() === 'export async function registerCustomElements() {') { + captureDataCascade = false; + captureComponents = true; + } + + if (captureDataCascade === true) { + dataCascade.push(line); + } + if (captureComponents === true) { + if ( + line.trim() === '// hydrate-able components' || + line.trim() === '// client-only components' + ) { + this.needsLoader = true; + } + componentDefinitions.push(line); + } + + if (line.trim() === '/* START - Rocket auto generated - do not touch */') { + captureDataCascade = true; + } + } + + this.dataCascade = dataCascade; + this.componentDefinitions = componentDefinitions; + } + + async getSourceFileContent() { + if (!this.sourceFileContent) { + this.setSourceFileContent((await readFile(this.sourceFilePath)).toString()); + } + return this.sourceFileContent; + } + + async syncDataCascade() { + try { + await this._syncDataCascade(); + } catch (error) { + // we tried to update the rocket header but something failed => user has to fix his code + // error will be shown by the render worker + } + } + + async _syncDataCascade() { + const dataFiles = []; + + // Use all `recursive.data.js` files up the tree + let possibleParent = path.dirname(this.sourceFilePath); + while (possibleParent.startsWith(this.inputDir)) { + const thisAndSubDirsFilePath = path.join(possibleParent, 'recursive.data.js'); + const fileDir = path.dirname(this.sourceFilePath); + if (existsSync(thisAndSubDirsFilePath)) { + const rel = path.relative(fileDir, thisAndSubDirsFilePath); + dataFiles.push({ + filePath: thisAndSubDirsFilePath, + exportModuleName: rel.startsWith('.') ? rel : `./${rel}`, + }); + } + possibleParent = path.dirname(possibleParent); + } + + // Add `local.data.js` if available + const thisDirFilePath = path.join(path.dirname(this.sourceFilePath), 'local.data.js'); + if (existsSync(thisDirFilePath)) { + dataFiles.push({ + filePath: thisDirFilePath, + exportModuleName: './local.data.js', + }); + } + + /** + * @type {Array<{ + * importName: string; + * importModuleName: string; + * as?: string; + * }>} + */ + const possibleImports = []; + for (const dataFile of dataFiles) { + const { filePath: dataFilePath, exportModuleName } = dataFile; + const readDataFile = await readFile(dataFilePath); + const [, exports] = parse(readDataFile.toString()); + + for (const dataExportName of exports) { + const foundIndex = possibleImports.findIndex(el => el.importName === dataExportName); + if (foundIndex >= 0) { + possibleImports[foundIndex].importModuleName = exportModuleName; + } else { + possibleImports.push({ + importName: dataExportName, + importModuleName: exportModuleName, + }); + } + } + } + + let contentWithoutRocketHeader = await this.getContentWithoutHeader(); + if (this.sourceFilePath.endsWith('.md')) { + contentWithoutRocketHeader = getServerCodeFromMd(contentWithoutRocketHeader); + } + if (this.sourceFilePath.endsWith('.html')) { + contentWithoutRocketHeader = getServerCodeFromHtml(contentWithoutRocketHeader); + } + const [thisImports, thisExports] = parse(contentWithoutRocketHeader); + + const thisImportNames = importsToImportNames(thisImports, contentWithoutRocketHeader); + const thisImportsAndExports = [...thisImportNames, ...thisExports]; + + for (const thisExport of thisImportsAndExports) { + const foundIndex = possibleImports.findIndex(el => el.importName === thisExport); + if (foundIndex >= 0) { + const asOriginalVariableName = `original${capitalizeFirstLetter( + possibleImports[foundIndex].importName, + )}`; + if (contentWithoutRocketHeader.includes(asOriginalVariableName)) { + // import { variableName as originalVariableName } instead + possibleImports[foundIndex].as = asOriginalVariableName; + } else { + // delete import as exported by user and asOriginalVariableName is not used in code + possibleImports.splice(foundIndex, 1); + } + } + } + + const exportNames = possibleImports.filter(el => !el.as).map(el => el.importName); + const exportsString = exportNames.length > 0 ? [`export { ${exportNames.join(', ')} };`] : []; + + const usedImports = new Map(); + for (const importObj of possibleImports) { + const importStatement = importObj.as + ? `${importObj.importName} as ${importObj.as}` + : `${importObj.importName}`; + if (usedImports.has(importObj.importModuleName)) { + usedImports.get(importObj.importModuleName).push(importStatement); + } else { + usedImports.set(importObj.importModuleName, [importStatement]); + } + } + + this.dataCascade = [ + ...[...usedImports.entries()].map( + ([importModuleName, imports]) => + `import { ${imports.join(', ')} } from '${importModuleName}';`, + ), + ...exportsString, + ]; + + await this.save(); + } + + async getContentWithoutHeader() { + const lines = (await this.getSourceFileContent()).split('\n'); + let startIndex = -1; + let endIndex = -1; + for (let i = 0; i < lines.length; i++) { + if (lines[i].trim() === '/* START - Rocket auto generated - do not touch */') { + startIndex = i; + } + if (lines[i].trim() === '/* END - Rocket auto generated - do not touch */') { + endIndex = i; + break; + } + } + + if (startIndex && !endIndex) { + throw new Error( + `No "/* END - Rocket auto generated - do not touch */" found in ${this.sourceFilePath}`, + ); + } + + if (startIndex >= 0 && endIndex >= 0) { + return lines.splice(endIndex + 1).join('\n'); + } + return lines.join('\n'); + } + + async set() { + const sourceRelativeFilePath = path.relative(this.inputDir, this.sourceFilePath); + + this.header = this.addLongFileHeaderComments( + [ + '/* START - Rocket auto generated - do not touch */', + `export const sourceRelativeFilePath = '${sourceRelativeFilePath}';`, + ...this.dataCascade, + ...this.componentDefinitions, + '/* END - Rocket auto generated - do not touch */', + ].join('\n'), + ); + + /** @type {string[]} */ + const lines = (await this.getSourceFileContent()).split('\n'); + let startIndex = -1; + let endIndex = -1; + for (let i = 0; i < lines.length; i++) { + if (lines[i].trim() === '/* START - Rocket auto generated - do not touch */') { + startIndex = i; + } + if (lines[i].trim() === '/* END - Rocket auto generated - do not touch */') { + endIndex = i; + break; + } + } + + if (startIndex && !endIndex) { + throw new Error( + `No "/* END - Rocket auto generated - do not touch */" found in ${this.sourceFilePath}`, + ); + } + + if (startIndex >= 0 && endIndex >= 0) { + lines.splice(startIndex, endIndex - startIndex + 1, this.header); + } else { + const extension = this.sourceFilePath.split('.').pop(); + + /** @type {string[]} */ + let wrapBefore = []; + /** @type {string[]} */ + let warpAfter = []; + switch (extension) { + case 'md': + wrapBefore = ['```js server']; + warpAfter = ['```']; + break; + case 'html': + wrapBefore = ['']; + break; + } + + lines.unshift([...wrapBefore, this.header, ...warpAfter, ''].join('\n')); + } + + this.updatedSourceFileContent = lines.join('\n'); + + return this.updatedSourceFileContent; + } + + /** + * @returns {Promise<{ needsAnotherRenderingPass: boolean }>} + */ + async save() { + if (!this.updatedSourceFileContent) { + await this.set(); + } + if (!this.updatedSourceFileContent) { + return { needsAnotherRenderingPass: false }; // for TS 🤷‍♂️ + } + + const existing = await this.getSourceFileContent(); + const updated = this.updatedSourceFileContent; + + // console.log({ CHANGED: existing !== updated }) + if (existing !== updated) { + // console.log({ existing, updated, CHANGED: existing !== updated, }); + await writeFile(this.sourceFilePath, updated); + this.sourceFileContent = updated; + return { needsAnotherRenderingPass: true }; + } + return { needsAnotherRenderingPass: false }; + } + + /** + * @param {string} fileHeader + * @returns {string} + */ + addLongFileHeaderComments(fileHeader) { + const linesWithComments = []; + if (this.longFileHeaderComment) { + for (const line of fileHeader.split('\n')) { + if (line.length > this.longFileHeaderWidth) { + const prefix = line.startsWith(' ') ? ' ' : ''; + const comment = `${prefix}${this.longFileHeaderComment}`; + // @ts-ignore + if (linesWithComments.at(-1) !== comment) { + // if line does not already have the comment then add it + linesWithComments.push(`${prefix}${this.longFileHeaderComment}`); + } + } + linesWithComments.push(line); + } + return linesWithComments.join('\n'); + } + return fileHeader; + } + + /** + * @param {Object} options + * @param {String} options.outputFileContent + * @param {String} options.outputFilePath + * @param {String} options.openGraphHtml + * @param {ComponentStrings} options.componentStrings + * @returns {Promise<{ needsAnotherRenderingPass: boolean }>} + */ + async syncComponents(options) { + try { + return this._syncComponents(options); + } catch (error) { + // we tried to update the rocket header but something failed => user has to fix his code + // error will be shown by the render worker + return { needsAnotherRenderingPass: false }; + } + } + + /** + * @param {Object} options + * @param {String} options.outputFileContent + * @param {String} options.outputFilePath + * @param {String} options.openGraphHtml + * @param {ComponentStrings} options.componentStrings + * @returns {Promise<{ needsAnotherRenderingPass: boolean }>} + */ + async _syncComponents({ outputFileContent, outputFilePath, componentStrings, openGraphHtml }) { + const componentsWithStrategy = getComponentsWithStrategy({ + outputFileContent, + componentStrings, + }); + if (openGraphHtml) { + const openGraphComponentsWithStrategy = getComponentsWithStrategy({ + outputFileContent: openGraphHtml, + componentStrings, + }); + for (const [key, component] of Object.entries(openGraphComponentsWithStrategy)) { + if (component.strategy === 'server' && !componentsWithStrategy[key]) { + component.strategy = 'server-open-graph-only'; + componentsWithStrategy[key] = component; + } + } + } + + const serverOnlyComponents = []; + const serverOnlyOpenGraphOnlyComponents = []; + const hydrateAbleComponents = []; + const clientComponents = []; + for (const [key, component] of Object.entries(componentsWithStrategy)) { + const importParts = component.importString.trim().split('::'); + if (component.strategy === 'server') { + serverOnlyComponents.push( + ` customElements.define('${key}', await import('${importParts[0]}').then(m => m.${importParts[1]}));`, + ); + } + if (component.strategy === 'server-open-graph-only') { + serverOnlyOpenGraphOnlyComponents.push( + ` customElements.define('${key}', await import('${importParts[0]}').then(m => m.${importParts[1]}));`, + ); + } + if (component.strategy.startsWith('hydrate')) { + hydrateAbleComponents.push( + ` customElements.define('${key}', await import('${importParts[0]}').then(m => m.${importParts[1]}));`, + ); + } + if (component.strategy === 'client') { + clientComponents.push( + ` // '${key}': () => import('${importParts[0]}').then(m => m.${importParts[1]}),`, + ); + } + } + if (serverOnlyComponents.length > 0) { + serverOnlyComponents.unshift(' // server-only components'); + } + if (serverOnlyOpenGraphOnlyComponents.length > 0) { + serverOnlyOpenGraphOnlyComponents.unshift(' // server-only open-graph only components'); + } + if (hydrateAbleComponents.length > 0) { + hydrateAbleComponents.unshift(' // hydrate-able components'); + } + if (clientComponents.length > 0) { + clientComponents.unshift(' // client-only components'); + } + + if ( + serverOnlyComponents.length > 0 || + serverOnlyOpenGraphOnlyComponents.length > 0 || + hydrateAbleComponents.length > 0 || + clientComponents.length > 0 + ) { + this.componentDefinitions = [ + 'export async function registerCustomElements() {', + ...serverOnlyComponents, + ...serverOnlyOpenGraphOnlyComponents, + ...hydrateAbleComponents, + ...clientComponents, + '}', + ]; + } else { + this.componentDefinitions = []; + } + + await this.set(); + const result = await this.save(); + if (hydrateAbleComponents.length > 0 || clientComponents.length > 0) { + this.needsLoader = true; + await this.saveHydrationFile({ outputFilePath, componentsWithStrategy }); + } else { + this.needsLoader = false; + } + return result; + } + + /** + * @param {Object} options + * @param {String} options.outputFilePath + * @param {ComponentsWithStrategy} options.componentsWithStrategy + * @returns {Promise} + */ + async saveHydrationFile({ outputFilePath, componentsWithStrategy }) { + if (Object.keys(componentsWithStrategy).length === 0) { + return; + } + + const hydrationFilePath = outputFilePath.replace('.html', '-loader-generated.js'); + const hydrateAbleComponents = []; + const clientOnlyComponents = []; + for (const [key, component] of Object.entries(componentsWithStrategy)) { + const importParts = component.importString.split('::'); + if (component.strategy.startsWith('hydrate')) { + hydrateAbleComponents.push( + ` '${key}': () => import('${importParts[0]}').then(m => m.${importParts[1]}),`, + ); + } + if (component.strategy === 'client') { + clientOnlyComponents.push( + `customElements.define('${key}', await import('${importParts[0]}').then(m => m.${importParts[1]}));`, + ); + } + } + + if (clientOnlyComponents.length > 0) { + clientOnlyComponents.unshift('await loader.setup();'); + clientOnlyComponents.unshift('// client-only components'); + } + + // TODO: optimize to not load full HydrationLoader if there are ONLY client-only components + const hydrationFileContent = [ + "import { HydrationLoader } from '@rocket/engine/hydration';", + '', + 'const hydrateAbleComponents = {', + ...hydrateAbleComponents, + '};', + '', + 'const loader = new HydrationLoader(hydrateAbleComponents);', + ...clientOnlyComponents, + '', + 'window.__ROCKET_HYDRATION_LOADER__ = loader;', + 'await loader.init();', + ].join('\n'); + + await writeFile(hydrationFilePath, hydrationFileContent); + } +} diff --git a/packages/engine/src/file-header/updateRocketHeader.js b/packages/engine/src/file-header/updateRocketHeader.js deleted file mode 100644 index a377391d..00000000 --- a/packages/engine/src/file-header/updateRocketHeader.js +++ /dev/null @@ -1,206 +0,0 @@ -import path from 'path'; -import fs from 'fs'; -import { writeFile, readFile } from 'fs/promises'; - -import { parse } from '../helpers/es-module-lexer.js'; -import { getServerCodeFromMd } from '../formats/getServerCodeFromMd.js'; -import { getServerCodeFromHtml } from '../formats/html.js'; -import { importsToImportNames } from './import-names.js'; - -/** - * @param {string} string - * @returns {string} - */ -function capitalizeFirstLetter(string) { - return string.charAt(0).toUpperCase() + string.slice(1); -} - -/** - * @param {string} content - * @param {string} header - * @param {string} filePath - * @returns {string} - */ -function setRocketHeader(content, header, filePath) { - const lines = content.toString().split('\n'); - - let startIndex = -1; - let endIndex = -1; - for (let i = 0; i < lines.length; i++) { - if (lines[i].trim() === '/* START - Rocket auto generated - do not touch */') { - startIndex = i; - } - if (lines[i].trim() === '/* END - Rocket auto generated - do not touch */') { - endIndex = i; - break; - } - } - - if (startIndex && !endIndex) { - throw new Error(`No "/* END - Rocket auto generated - do not touch */" found in ${filePath}`); - } - - if (startIndex >= 0 && endIndex >= 0) { - lines.splice(startIndex, endIndex - startIndex + 1, header); - } else { - const extension = filePath.split('.').pop(); - - /** @type {string[]} */ - let wrapBefore = []; - /** @type {string[]} */ - let warpAfter = []; - switch (extension) { - case 'md': - wrapBefore = ['```js server']; - warpAfter = ['```']; - break; - case 'html': - wrapBefore = ['']; - break; - } - - lines.unshift([...wrapBefore, header, ...warpAfter, ''].join('\n')); - } - - return lines.join('\n'); -} - -/** - * - * @param {string} content - * @param {object} options - * @param {string} options.filePath - * @param {string} options.docsDir - * @returns {Promise} - */ -async function generateRocketHeader(content, { filePath, docsDir }) { - const dataFiles = []; - - // Use all `recursive.data.js` files up the tree - let possibleParent = path.dirname(filePath); - while (possibleParent.startsWith(docsDir)) { - const thisAndSubDirsFilePath = path.join(possibleParent, 'recursive.data.js'); - const fileDir = path.dirname(filePath); - if (fs.existsSync(thisAndSubDirsFilePath)) { - const rel = path.relative(fileDir, thisAndSubDirsFilePath); - dataFiles.push({ - filePath: thisAndSubDirsFilePath, - exportModuleName: rel.startsWith('.') ? rel : `./${rel}`, - }); - } - possibleParent = path.dirname(possibleParent); - } - - // Add `local.data.js` if available - const thisDirFilePath = path.join(path.dirname(filePath), 'local.data.js'); - if (fs.existsSync(thisDirFilePath)) { - dataFiles.push({ - filePath: thisDirFilePath, - exportModuleName: './local.data.js', - }); - } - - /** - * @type {Array<{ - * importName: string; - * importModuleName: string; - * as?: string; - * }>} - */ - const possibleImports = []; - for (const dataFile of dataFiles) { - const { filePath: dataFilePath, exportModuleName } = dataFile; - const readDataFile = await readFile(dataFilePath); - const [, exports] = parse(readDataFile.toString()); - - for (const dataExportName of exports) { - const foundIndex = possibleImports.findIndex(el => el.importName === dataExportName); - if (foundIndex >= 0) { - possibleImports[foundIndex].importModuleName = exportModuleName; - } else { - possibleImports.push({ - importName: dataExportName, - importModuleName: exportModuleName, - }); - } - } - } - - let contentWithoutRocketHeader = setRocketHeader(content, '', filePath); - if (filePath.endsWith('.md')) { - contentWithoutRocketHeader = getServerCodeFromMd(contentWithoutRocketHeader); - } - if (filePath.endsWith('.html')) { - contentWithoutRocketHeader = getServerCodeFromHtml(contentWithoutRocketHeader); - } - - const [thisImports, thisExports] = parse(contentWithoutRocketHeader); - - const thisImportNames = importsToImportNames(thisImports, contentWithoutRocketHeader); - const thisImportsAndExports = [...thisImportNames, ...thisExports]; - - for (const thisExport of thisImportsAndExports) { - const foundIndex = possibleImports.findIndex(el => el.importName === thisExport); - if (foundIndex >= 0) { - const asOriginalVariableName = `original${capitalizeFirstLetter( - possibleImports[foundIndex].importName, - )}`; - if (contentWithoutRocketHeader.includes(asOriginalVariableName)) { - // import { variableName as originalVariableName } instead - possibleImports[foundIndex].as = asOriginalVariableName; - } else { - // delete import as exported by user and asOriginalVariableName is not used in code - possibleImports.splice(foundIndex, 1); - } - } - } - - const exportNames = possibleImports.filter(el => !el.as).map(el => el.importName); - const exportsString = exportNames.length > 0 ? [`export { ${exportNames.join(', ')} };`] : []; - - const usedImports = new Map(); - for (const importObj of possibleImports) { - const importStatement = importObj.as - ? `${importObj.importName} as ${importObj.as}` - : `${importObj.importName}`; - if (usedImports.has(importObj.importModuleName)) { - usedImports.get(importObj.importModuleName).push(importStatement); - } else { - usedImports.set(importObj.importModuleName, [importStatement]); - } - } - - const sourceRelativeFilePath = path.relative(docsDir, filePath); - // TODO: format with prettier or add + end - const header = [ - '/* START - Rocket auto generated - do not touch */', - `export const sourceRelativeFilePath = '${sourceRelativeFilePath}';`, - ...[...usedImports.entries()].map( - ([importModuleName, imports]) => - `import { ${imports.join(', ')} } from '${importModuleName}';`, - ), - ...exportsString, - '/* END - Rocket auto generated - do not touch */', - ].join('\n'); - - return header; -} - -/** - * @param {string} filePath - * @param {string} docsDir - */ -export async function updateRocketHeader(filePath, docsDir) { - const content = (await readFile(filePath)).toString(); - try { - const header = await generateRocketHeader(content, { filePath, docsDir }); - const updatedContent = setRocketHeader(content, header, filePath); - if (content !== updatedContent) { - await writeFile(filePath, updatedContent); - } - } catch (error) { - // we tried to update the rocket header but something failed => user has to fix his code - // error will be shown by the render worker - } -} diff --git a/packages/engine/src/file-header/validateComponentImportString.js b/packages/engine/src/file-header/validateComponentImportString.js new file mode 100644 index 00000000..5bd84bb0 --- /dev/null +++ b/packages/engine/src/file-header/validateComponentImportString.js @@ -0,0 +1,12 @@ +const regexOnlyBareImport = /^[a-z|@|/|#].*/; + +/** + * @param {string} importString + * @returns {Boolean} + */ +export function validateComponentImportString(importString) { + if (typeof importString === 'string' && importString.match(regexOnlyBareImport)) { + return true; + } + return false; +} diff --git a/packages/engine/src/helpers/findJsDependencies.js b/packages/engine/src/helpers/findJsDependencies.js index c800d17c..f437e33f 100644 --- a/packages/engine/src/helpers/findJsDependencies.js +++ b/packages/engine/src/helpers/findJsDependencies.js @@ -44,8 +44,9 @@ export async function findJsDependencies(filePath, options = {}) { importsToScan.add(pathToDependency); dependencies.add(pathToDependency); } catch (e) { - console.log(`Failed to resolve dependency "${i.n}" in "${filePath}"`); - console.log(e); + // we do not throw here as we only use this function to enhance DX - the actual error will be thrown/shown by renderWorker + // console.log(`Failed to resolve dependency "${i.n}" in "${filePath}"`); + // console.log(e); } } } @@ -83,8 +84,9 @@ export async function findJsDependencies(filePath, options = {}) { dependencies.add(pathToDependency); } } catch (e) { - console.log(`Failed to resolve dependency "${i.n}" in "${dep}"`); - console.log(e); + // we do not throw here as we only use this function to enhance DX - the actual error will be thrown/shown by renderWorker + // console.log(`Failed to resolve dependency "${i.n}" in "${dep}"`); + // console.log(e); } } } diff --git a/packages/engine/src/helpers/transformFile.js b/packages/engine/src/helpers/transformFile.js index 300fdcb2..26ab6b31 100644 --- a/packages/engine/src/helpers/transformFile.js +++ b/packages/engine/src/helpers/transformFile.js @@ -1,13 +1,17 @@ import { applyPlugins } from 'plugins-manager'; import { AdjustAssetUrls } from '../transformers/AdjustAssetUrls.js'; +import { InjectLoaderFile } from '../transformers/InjectLoaderFile.js'; /** @type {import('../../types/main.js').MetaPluginOfEngine[]} */ -const defaultPlugins = [{ plugin: AdjustAssetUrls, options: {} }]; +const defaultPlugins = [ + { plugin: AdjustAssetUrls, options: {} }, + { plugin: InjectLoaderFile, options: {} }, +]; /** * @param {string} content - * @param {{ setupPlugins: any, sourceFilePath: string, outputFilePath: string, sourceRelativeFilePath: string, outputRelativeFilePath: string, url:string }} options - * @returns + * @param {{ setupPlugins: any, sourceFilePath: string, outputFilePath: string, sourceRelativeFilePath: string, outputRelativeFilePath: string, url:string; needsLoader: boolean }} options + * @returns {Promise} */ export async function transformFile(content, options) { const finalConfig = applyPlugins(options, defaultPlugins); diff --git a/packages/engine/src/hydration/HydrationLoader.js b/packages/engine/src/hydration/HydrationLoader.js new file mode 100644 index 00000000..734ff56a --- /dev/null +++ b/packages/engine/src/hydration/HydrationLoader.js @@ -0,0 +1,276 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +/* eslint-disable no-prototype-builtins */ +import { evaluate } from './evaluate.js'; +import { extractStrategies } from './extractStrategies.js'; + +export class HydrationLoader { + /** @type {import('../../types/main').Components} */ + components = {}; + isSetup = false; + + /** @type {import('../../types/main').ElementWithStrategy[]} */ + elements = []; + + /** @type {{ [key: string]: MediaQueryList }} */ + mediaQueries = {}; + + /** + * @param {import('../../types/main').Components} components + */ + constructor(components) { + this.components = components; + } + + /** + * + * @param {number} index + * @param {object} options + * @param {Event} [options.ev] + * @returns {Promise<{ needsCleanup: boolean }>} + */ + async checkElement(index, { ev } = {}) { + const el = this.elements[index]; + const allResolveAble = evaluate({ + strategyTemplate: el.strategyTemplate, + strategies: el.strategies, + }); + if (allResolveAble) { + await this.setup(); + const loadFn = this.components[el.tagName]; + if (loadFn) { + const klass = await loadFn(); + customElements.define(el.tagName, klass); + } + if (el.node.updateComplete) { + await el.node.updateComplete; + } + + for (let i = 0; i < this.elements.length; i += 1) { + if (this.elements[i].tagName === el.tagName) { + this.elements[i].deleteMe = true; + } + } + + if (ev) { + // @ts-ignore + const reFire = ev.path[0]; + if (reFire) { + reFire.click(); + } + } + + return { needsCleanup: true }; + } + return { needsCleanup: false }; + } + + cleanup() { + const length = this.elements.length - 1; + for (let i = length; i >= 0; i--) { + if (this.elements[i].deleteMe) { + if (this.intersectionObserver) { + if (this.elements[i].strategies.some(strategy => strategy.type === 'onVisible')) { + this.intersectionObserver.unobserve(this.elements[i].node); + } + } + this.elements.splice(i, 1); + } + } + } + + /** + * @returns {import('../../types/main').ElementWithStrategy[]} + */ + gatherElements() { + const els = document.querySelectorAll('[loading]'); + /** @type {import('../../types/main').ElementWithStrategy[]} */ + const elements = []; + for (const el of els) { + const strategyAttribute = el.getAttribute('loading'); + if (!strategyAttribute) { + continue; + } + + const tagName = el.tagName.toLowerCase(); + if (strategyAttribute.startsWith('hydrate:')) { + const hydrationStrategy = strategyAttribute.substring('hydrate:'.length); + const strategies = extractStrategies(hydrationStrategy); + elements.push({ + tagName, + node: el, + ...strategies, + }); + } + } + return elements; + } + + /** + * + * @param {Object} param1 + * @param {EventTarget} param1.target + * @param {String} param1.strategyType + * @param {String} [param1.strategyOptions] + * @param {Boolean} param1.resolveAble + * @param {Object} [options] + */ + async setResolveAbleOn({ target, strategyType, strategyOptions, resolveAble }, options = {}) { + let needsCleanup = false; + const foundIndex = this.elements.findIndex(el => el.node === target && !el.deleteMe); + if (foundIndex !== -1) { + for (let i = 0; i < this.elements[foundIndex].strategies.length; i += 1) { + if ( + this.elements[foundIndex].strategies[i].type === strategyType && + this.elements[foundIndex].strategies[i].options === strategyOptions + ) { + this.elements[foundIndex].strategies[i].resolveAble = resolveAble; + ({ needsCleanup } = await this.checkElement(foundIndex, options)); + } + } + } + if (needsCleanup) { + this.cleanup(); + } + } + + async init() { + if (Object.keys(this.components).length === 0) { + return; + } + this.elements = this.gatherElements(); + + let needsCleanup = false; + for (let i = 0; i < this.elements.length; i += 1) { + ({ needsCleanup } = await this.checkElement(i)); + } + if (needsCleanup) { + await this.cleanup(); + } + + await this.handleOnVisible(); + await this.handleOnClick(); + + await this.handleOnMedia(); + } + + async handleOnMedia() { + for (const el of this.elements) { + for (const strategy of el.strategies) { + if (strategy.type === 'onMedia' && strategy.options) { + if (!this.mediaQueries[strategy.options]) { + this.mediaQueries[strategy.options] = window.matchMedia(strategy.options); + } + + // TODO: remove event listener on cleanup if element gets removed + this.mediaQueries[strategy.options].addEventListener('change', ev => { + if (ev.matches) { + this.setResolveAbleOn({ + target: el.node, + strategyType: strategy.type, + strategyOptions: strategy.options, + resolveAble: true, + }); + } else { + this.setResolveAbleOn({ + target: el.node, + strategyType: strategy.type, + strategyOptions: strategy.options, + resolveAble: false, + }); + } + }); + + // Initial check + if (this.mediaQueries[strategy.options].matches) { + this.setResolveAbleOn({ + target: el.node, + strategyType: strategy.type, + strategyOptions: strategy.options, + resolveAble: true, + }); + } + } + } + } + } + + async handleOnClick() { + document.body.addEventListener('click', async ev => { + if (!ev.target) { + return; + } + this.setResolveAbleOn( + { target: ev.target, strategyType: 'onClick', resolveAble: true }, + { ev }, + ); + + // reset the onClick resolveAble if the click did not resulted in the hydration of the element + setTimeout(() => { + if (!ev.target) { + return; + } + this.setResolveAbleOn({ target: ev.target, strategyType: 'onClick', resolveAble: false }); + }, 10); + }); + } + + async handleOnVisible() { + this.intersectionObserver = new IntersectionObserver(entries => { + for (const entry of entries) { + if (entry.isIntersecting) { + this.setResolveAbleOn({ + target: entry.target, + strategyType: 'onVisible', + resolveAble: true, + }); + } else { + this.setResolveAbleOn({ + target: entry.target, + strategyType: 'onVisible', + resolveAble: false, + }); + } + } + }); + + for (const el of this.elements) { + for (const strategy of el.strategies) { + if (strategy.type === 'onVisible') { + this.intersectionObserver.observe(el.node); + } + } + } + } + + async setup() { + if (this.isSetup === false) { + // Start fetching the Lit hydration support module (note the absence + // of "await" -- we don't want to block yet). + const litHydrateSupportInstalled = import('lit/experimental-hydrate-support.js'); + + // Check if we require the declarative shadow DOM polyfill. As of + // February 2022, Chrome and Edge have native support, but Firefox + // and Safari don't yet. + if (!HTMLTemplateElement.prototype.hasOwnProperty('shadowRoot')) { + // Fetch the declarative shadow DOM polyfill. + const { hydrateShadowRoots } = await import( + '@webcomponents/template-shadowroot/template-shadowroot.js' + ); + + // Apply the polyfill. This is a one-shot operation, so it is important + // it happens after all HTML has been parsed. + hydrateShadowRoots(document.body); + + // At this point, browsers without native declarative shadow DOM + // support can paint the initial state of your components! + document.body.removeAttribute('dsd-pending'); + } + + // The Lit hydration support module must be installed before we can + // load any component definitions. Wait until it's ready. + await litHydrateSupportInstalled; + + this.isSetup = true; + } + } +} diff --git a/packages/engine/src/hydration/evaluate.js b/packages/engine/src/hydration/evaluate.js new file mode 100644 index 00000000..61796f72 --- /dev/null +++ b/packages/engine/src/hydration/evaluate.js @@ -0,0 +1,52 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +/** + * @param {object} options + * @param {string} options.strategyTemplate + * @param {import("../../types/main").Strategy[]} options.strategies + * @returns {boolean} + */ +export function evaluate({ strategyTemplate, strategies }) { + // @ts-ignore + const conditions = strategyTemplate.replace(/{{(\d+)}}/g, (match, number) => { + if (strategies[number]) { + return strategies[number].resolveAble ? 1 : 0; + } + return match; + }); + const result = evaluateConditions(conditions); + return result; +} + +/** + * @param {string} input + * @returns {boolean} + */ +export function evaluateConditions(input) { + let state; + let mode = 'and'; + + const str = input.replace('&&', '&').replace('||', '|'); + + for (const char of str) { + if (char === ' ') { + continue; + } + if (char === '&') { + mode = 'and'; + } + if (char === '|') { + mode = 'or'; + } + // @ts-ignore + if (!isNaN(char)) { + // is number + const i = parseInt(char); + state = state === undefined ? i : mode === 'and' ? state & i : state | i; + if (mode === 'or' && state === 1) { + return true; + } + } + } + return !!state; +} diff --git a/packages/engine/src/hydration/extractStrategies.js b/packages/engine/src/hydration/extractStrategies.js new file mode 100644 index 00000000..eeb56cca --- /dev/null +++ b/packages/engine/src/hydration/extractStrategies.js @@ -0,0 +1,86 @@ +/** + * @param {string} str + * @returns {string[]} + */ +function getParts(str) { + const parts = []; + let captured = ''; + for (const char of str.split('')) { + if ((char === '&' && captured.endsWith('&')) || (char === '|' && captured.endsWith('|'))) { + parts.push(captured.slice(0, -1).trim()); + parts.push(char.repeat(2)); + captured = ''; + } else { + captured += char; + } + } + + if (captured) { + parts.push(captured.trim()); + } + + return parts; +} + +/** + * + * @param {string} part + * @param {string} type + * @returns {{ type: string; resolveAble: boolean; options?: string; }} + */ +function getStrategy(part, type) { + /** @type {{ type: string; resolveAble: boolean; options?: string; }} */ + const strategy = { + type, + resolveAble: false, + }; + if (part.length > type.length) { + const rawOptions = part.slice(type.length).trim(); + if (rawOptions.startsWith("('") && rawOptions.endsWith("')")) { + const options = rawOptions.slice(2, -2); + strategy.options = options; + } + } + if (type === 'onIdle' || type === 'onDelay' || type === 'onClientLoad') { + strategy.resolveAble = true; + } + return strategy; +} + +/** + * @param {string} input + * @returns {import("../../types/main").LoadingStrategy} + */ +export function extractStrategies(input) { + const parts = getParts(input); + + /** @type {import("../../types/main").LoadingStrategy} */ + const result = { + strategyAttribute: input, + strategies: [], + strategyTemplate: '', + }; + + let templatePartsIndex = 0; + for (const [i, part] of parts.entries()) { + const type = part.includes('(') ? part.substring(0, part.indexOf('(')) : part; + switch (type) { + // global events + case 'onClientLoad': + case 'onClick': + // element events eslint fall through + case 'onHover': + case 'onMedia': + case 'onVisible': + // modifiers eslint fall through + case 'onIdle': + case 'onDelay': + result.strategies.push(getStrategy(part, type)); + parts[i] = `{{${templatePartsIndex}}}`; + templatePartsIndex += 1; + } + } + result.strategyTemplate = parts.join(' '); + + return result; +} diff --git a/packages/engine/src/index.hydration.js b/packages/engine/src/index.hydration.js new file mode 100644 index 00000000..4b046615 --- /dev/null +++ b/packages/engine/src/index.hydration.js @@ -0,0 +1 @@ +export { HydrationLoader } from './hydration/HydrationLoader.js'; diff --git a/packages/engine/src/transformers/InjectLoaderFile.js b/packages/engine/src/transformers/InjectLoaderFile.js new file mode 100644 index 00000000..c41099f4 --- /dev/null +++ b/packages/engine/src/transformers/InjectLoaderFile.js @@ -0,0 +1,34 @@ +import path from 'path'; + +export class InjectLoaderFile { + /** + * @param {string} source + * @param {object} options + * @param {string} options.url + * @param {string} options.sourceFilePath + * @param {string} options.sourceRelativeFilePath + * @param {string} options.outputFilePath + * @param {string} options.outputRelativeFilePath + * @param {boolean} options.needsLoader + * @returns {Promise} + */ + async transform(source, { outputFilePath, needsLoader }) { + let output = source; + + if (outputFilePath.endsWith('.html') && !outputFilePath.endsWith('.opengraph.html')) { + const hydrationFilePath = outputFilePath.replace('.html', '-loader-generated.js'); + const fileName = path.basename(hydrationFilePath); + if (needsLoader) { + if (output.includes('')) { + output = output.replace( + '', + `\n`, + ); + } else { + output += `\n`; + } + } + } + return output; + } +} diff --git a/packages/engine/src/web-menu/PageTree.js b/packages/engine/src/web-menu/PageTree.js index aa67322e..ba0c656e 100644 --- a/packages/engine/src/web-menu/PageTree.js +++ b/packages/engine/src/web-menu/PageTree.js @@ -232,8 +232,9 @@ export class PageTree { this.pageTreeChangedOnSave = false; const newContent = JSON.stringify(this.tree, null, 2); if (existsSync(this.dataFilePath)) { - const content = await readFile(this.dataFilePath); - if (content.toString() !== newContent) { + const content = (await readFile(this.dataFilePath)).toString(); + + if (content !== newContent) { this.pageTreeChangedOnSave = true; await writeFile(this.dataFilePath, newContent); } diff --git a/packages/engine/src/worker/importViaWorker.js b/packages/engine/src/worker/importViaWorker.js index 4d1b3605..df2026d0 100644 --- a/packages/engine/src/worker/importViaWorker.js +++ b/packages/engine/src/worker/importViaWorker.js @@ -30,9 +30,10 @@ async function getWorker(sourceFilePath) { /** * @param {object} options * @param {string} options.sourceFilePath + * @param {Boolean} [options.throwOnError] * @returns */ -export function importViaWorker({ sourceFilePath }) { +export function importViaWorker({ sourceFilePath, throwOnError = false }) { return new Promise((resolve, reject) => { getWorker(sourceFilePath).then(worker => { /** @@ -59,6 +60,7 @@ export function importViaWorker({ sourceFilePath }) { worker.once('error', handleError); worker.postMessage({ sourceFilePath, + throwOnError, }); }); }); diff --git a/packages/engine/src/worker/importWorker.js b/packages/engine/src/worker/importWorker.js index b24e509d..558ec349 100644 --- a/packages/engine/src/worker/importWorker.js +++ b/packages/engine/src/worker/importWorker.js @@ -10,7 +10,7 @@ import { parentPort } from 'worker_threads'; * this imports the actual source file and grabs all exported string and number values */ parentPort?.on('message', message => { - const { sourceFilePath } = message; + const { sourceFilePath, throwOnError } = message; (async () => { let importFilePath = sourceFilePath; @@ -35,6 +35,9 @@ parentPort?.on('message', message => { } } } catch (error) { + if (throwOnError) { + throw error; + } // if we can't import we don't add the data to the page } diff --git a/packages/engine/src/worker/renderViaWorker.js b/packages/engine/src/worker/renderViaWorker.js index cbe1c1fd..9d815f71 100644 --- a/packages/engine/src/worker/renderViaWorker.js +++ b/packages/engine/src/worker/renderViaWorker.js @@ -35,6 +35,8 @@ let isRendering = ''; * @param {string} options.outputDir * @param {string} options.inputDir * @param {string} options.renderMode + * @param {boolean} options.needsLoader + * @param {boolean} options.throwOnError * @returns {Promise} */ export function renderViaWorker({ @@ -42,6 +44,8 @@ export function renderViaWorker({ inputDir, outputDir, renderMode = 'development', + needsLoader = false, + throwOnError = false, }) { return new Promise((resolve, reject) => { getWorker(sourceFilePath).then(worker => { @@ -68,7 +72,11 @@ export function renderViaWorker({ isRendering = ''; worker.removeListener('error', handleError); if (result.passOnError) { - reject(result.passOnError); + if (throwOnError) { + reject(result.passOnError); + } else { + resolve(result); + } } if (result.sourceFilePath === sourceFilePath) { resolve(result); @@ -84,6 +92,8 @@ export function renderViaWorker({ outputDir, inputDir, renderMode, + needsLoader, + throwOnError, }); }); }); diff --git a/packages/engine/src/worker/renderWorker.js b/packages/engine/src/worker/renderWorker.js index 92fe44c1..6fd3f466 100644 --- a/packages/engine/src/worker/renderWorker.js +++ b/packages/engine/src/worker/renderWorker.js @@ -16,6 +16,7 @@ import { transformFile } from '../helpers/transformFile.js'; import { litServerRender } from '../helpers/litServerRender.js'; import { generateErrorPage } from './generateErrorPage.js'; +import { validateComponentImportString } from '../file-header/validateComponentImportString.js'; /** * @@ -23,10 +24,22 @@ import { generateErrorPage } from './generateErrorPage.js'; * @param {string} options.sourceFilePath * @param {string} options.outputDir * @param {string} options.inputDir + * @param {Boolean} options.needsLoader + * @param {Boolean} options.throwOnError * @param {'development'|'production'} options.renderMode */ -async function renderFile({ sourceFilePath, outputDir, inputDir, renderMode = 'development' }) { +async function renderFile({ + sourceFilePath, + outputDir, + inputDir, + renderMode = 'development', + needsLoader = false, + throwOnError = false, +}) { let fileContent = ''; + let openGraphHtml = ''; + /** @type {{ [key: string]: string; }} */ + let componentStrings = {}; /** @type {Error | undefined} */ let passOnError; @@ -47,6 +60,25 @@ async function renderFile({ sourceFilePath, outputDir, inputDir, renderMode = 'd const { default: content, ...data } = await import(toImportFilePath); const { layout, openGraphLayout } = data; + if (data.components) { + for (const [tagName, importString] of Object.entries(data.components)) { + if (validateComponentImportString(importString)) { + componentStrings[tagName] = importString; + } else { + throw new Error( + [ + `Bad component import: "${importString}"`, + ` for: "${tagName}"`, + ` while rendering: ${sourceFilePath}`, + ' here are some valid examples of component imports:', + ` 'my-el': '@my-scoped/my-lib/MyEl.js::MyEl'`, + ` 'my-el': 'my-lib/MyEl.js::MyEl`, + ` 'my-el': 'my-lib/components/MyEl::default`, + ].join('\n'), + ); + } + } + } keepConvertedFiles = data.keepConvertedFiles; const url = sourceRelativeFilePathToUrl(sourceRelativeFilePath); @@ -87,12 +119,16 @@ async function renderFile({ sourceFilePath, outputDir, inputDir, renderMode = 'd fileContent = templateResult; } else { // Load components server side - if (data.components) { - for (const tagName of Object.keys(data.components)) { - const componentFn = data.components[tagName]; - if (typeof componentFn === 'function') { - const componentClass = await componentFn(); - customElements.define(tagName, componentClass); + if (data.registerCustomElements) { + try { + await data.registerCustomElements(); + } catch (error) { + // one of the server side components could not be imported + // during start (throwError === false): render it without the server components (no error page) + // this will trigger an additional rendering pass (with throwError true) where hopefully the rocket header imports will be corrected + // if not it throws and the user needs to adjust its "components" { 'tag-name': 'bare-import::ClassName' } to be valid + if (throwOnError) { + throw error; } } } @@ -107,6 +143,7 @@ async function renderFile({ sourceFilePath, outputDir, inputDir, renderMode = 'd sourceRelativeFilePath, outputRelativeFilePath, url, + needsLoader, }); fileContent = fileContent.trim(); @@ -132,23 +169,24 @@ async function renderFile({ sourceFilePath, outputDir, inputDir, renderMode = 'd typeof openGraphLayout.render === 'function' ? openGraphLayout.render(layoutData) : openGraphLayout(layoutData); - const openGraphHtml = await litServerRender(openGraphTemplateResult); + const rawOpenGraphHtml = await litServerRender(openGraphTemplateResult); - let processedOpenGraphHtml = await transformFile(openGraphHtml, { + openGraphHtml = await transformFile(rawOpenGraphHtml, { setupPlugins: data.setupEnginePlugins, sourceFilePath, outputFilePath: layoutData.openGraphOutputFilePath, sourceRelativeFilePath, outputRelativeFilePath: layoutData.openGraphOutputRelativeFilePath, url: layoutData.openGraphUrl, + needsLoader, }); - processedOpenGraphHtml = processedOpenGraphHtml.trim(); + openGraphHtml = openGraphHtml.trim(); // remove leading/ending lit markers as with them web dev server falsy thinks this page is a HTML fragment and will not inject websockets - processedOpenGraphHtml = processedOpenGraphHtml.replace(/^/gm, ''); - processedOpenGraphHtml = processedOpenGraphHtml.replace(/$/gm, ''); + openGraphHtml = openGraphHtml.replace(/^/gm, ''); + openGraphHtml = openGraphHtml.replace(/$/gm, ''); - await writeFile(layoutData.openGraphOutputFilePath, processedOpenGraphHtml); + await writeFile(layoutData.openGraphOutputFilePath, openGraphHtml); } } catch (error) { const typed = /** @type {Error} */ (error); @@ -171,6 +209,8 @@ async function renderFile({ sourceFilePath, outputDir, inputDir, renderMode = 'd sourceRelativeFilePath, passOnError, keepConvertedFiles, + componentStrings, + openGraphHtml, }; parentPort?.postMessage(result); @@ -178,7 +218,7 @@ async function renderFile({ sourceFilePath, outputDir, inputDir, renderMode = 'd parentPort?.on('message', message => { if (message.action === 'renderFile') { - const { sourceFilePath, outputDir, renderMode, inputDir } = message; - renderFile({ sourceFilePath, outputDir, renderMode, inputDir }); + const { sourceFilePath, outputDir, renderMode, inputDir, needsLoader, throwOnError } = message; + renderFile({ sourceFilePath, outputDir, renderMode, inputDir, needsLoader, throwOnError }); } }); diff --git a/packages/engine/test-node/12-playwright.spec.js b/packages/engine/test-node/12-playwright.spec.js index 7f6d03f0..fa730a96 100644 --- a/packages/engine/test-node/12-playwright.spec.js +++ b/packages/engine/test-node/12-playwright.spec.js @@ -2,7 +2,7 @@ import { test, expect } from '@playwright/test'; import { setupTestEngine } from './test-helpers.js'; test('reloads current window on dependency change', async ({ page }) => { - const { engine, writeSource, anEngineEvent } = await setupTestEngine( + const { engine, writeSource, anEngineEvent, cleanup } = await setupTestEngine( 'fixtures/12-playwright/01-file-change-reloads/docs', ); await writeSource('name.js', "export const name = 'Home';"); @@ -20,4 +20,6 @@ test('reloads current window on dependency change', async ({ page }) => { await expect(title).toHaveText('index'); await expect(name).toHaveText('New Home'); + + await cleanup(); }); diff --git a/packages/engine/test-node/13-config.test.js b/packages/engine/test-node/13-config.test.js index 1a1cf057..b83f8336 100644 --- a/packages/engine/test-node/13-config.test.js +++ b/packages/engine/test-node/13-config.test.js @@ -73,4 +73,39 @@ describe('Config', () => { apiServer.close(); await cleanup(); }); + + it('03: can add a comment to lines longer then x characters in the file header', async () => { + const { build, readSource } = await setupTestEngine( + 'fixtures/13-config/03-long-file-header-comment/pages', + { + longFileHeaderWidth: 100, + longFileHeaderComment: '// prettier-ignore', + }, + ); + + await build(); + + expect(readSource('index.rocket.js', { format: false })).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + '// prettier-ignore', + "import { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components } from './local.data.js';", + '// prettier-ignore', + 'export { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + ' // prettier-ignore', + " customElements.define('my-el', await import('@test/components').then(m => m.MyVeryLongElementName));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => `', + ' This will be a very long line that will explain a complex topic in multiple paragraphs. The level of detail is important.', + ' ', + '`;', + '', + ].join('\n'), + ); + }); }); diff --git a/packages/engine/test-node/14-components.test.js b/packages/engine/test-node/14-components.test.js deleted file mode 100644 index bd5e44af..00000000 --- a/packages/engine/test-node/14-components.test.js +++ /dev/null @@ -1,23 +0,0 @@ -import chai from 'chai'; -import { setupTestEngine } from './test-helpers.js'; - -const { expect } = chai; - -describe('Components', () => { - it('01: loads components server side by default', async () => { - const { build, readOutput } = await setupTestEngine( - 'fixtures/14-components/01-load-server-side/docs', - ); - await build(); - - expect(readOutput('index.html')).to.equal( - [ - '

', - ' ', - '

', - ].join('\n'), - ); - }); -}); diff --git a/packages/engine/test-node/14a-components-stategies.test.js b/packages/engine/test-node/14a-components-stategies.test.js new file mode 100644 index 00000000..b3eb9e9c --- /dev/null +++ b/packages/engine/test-node/14a-components-stategies.test.js @@ -0,0 +1,259 @@ +import chai from 'chai'; + +import { evaluateConditions, evaluate } from '../src/hydration/evaluate.js'; +import { extractStrategies } from '../src/hydration/extractStrategies.js'; +import { validateComponentImportString } from '../src/file-header/validateComponentImportString.js'; + +const { expect } = chai; + +describe('hydration condition', () => { + describe('evaluateConditions', () => { + it('direct value', async () => { + expect(evaluateConditions('1')).to.be.true; + expect(evaluateConditions('0')).to.be.false; + }); + + it('and', async () => { + expect(evaluateConditions('0 && 0')).to.be.false; + expect(evaluateConditions('0 && 1')).to.be.false; + expect(evaluateConditions('1 && 0')).to.be.false; + expect(evaluateConditions('1 && 1')).to.be.true; + }); + + it('or', async () => { + expect(evaluateConditions('0 || 0')).to.be.false; + expect(evaluateConditions('0 || 1')).to.be.true; + expect(evaluateConditions('1 || 0')).to.be.true; + expect(evaluateConditions('1 || 1')).to.be.true; + }); + + it('and or', async () => { + expect(evaluateConditions('0 && 1 || 1')).to.be.true; + expect(evaluateConditions('1 && 1 || 0')).to.be.true; + expect(evaluateConditions('1 || 1 && 0')).to.be.true; + expect(evaluateConditions('0 || 1 && 0')).to.be.true; + }); + }); + + describe('extractStrategies', () => { + it('single strategy not default resolveAble', async () => { + expect(extractStrategies(`onClick`)).to.deep.equal({ + strategyAttribute: 'onClick', + strategyTemplate: '{{0}}', + strategies: [{ type: 'onClick', resolveAble: false }], + }); + expect(extractStrategies(`onHover`)).to.deep.equal({ + strategyAttribute: 'onHover', + strategyTemplate: '{{0}}', + strategies: [{ type: 'onHover', resolveAble: false }], + }); + + expect(extractStrategies(`onMedia`)).to.deep.equal({ + strategyAttribute: 'onMedia', + strategyTemplate: '{{0}}', + strategies: [{ type: 'onMedia', resolveAble: false }], + }); + expect(extractStrategies(`onVisible`)).to.deep.equal({ + strategyAttribute: 'onVisible', + strategyTemplate: '{{0}}', + strategies: [{ type: 'onVisible', resolveAble: false }], + }); + }); + + it('single strategy default resolveAble', async () => { + expect(extractStrategies(`onClientLoad`)).to.deep.equal({ + strategyAttribute: 'onClientLoad', + strategyTemplate: '{{0}}', + strategies: [{ type: 'onClientLoad', resolveAble: true }], + }); + expect(extractStrategies(`onIdle`)).to.deep.equal({ + strategyAttribute: 'onIdle', + strategyTemplate: '{{0}}', + strategies: [{ type: 'onIdle', resolveAble: true }], + }); + expect(extractStrategies(`onDelay`)).to.deep.equal({ + strategyAttribute: 'onDelay', + strategyTemplate: '{{0}}', + strategies: [{ type: 'onDelay', resolveAble: true }], + }); + }); + + it('options', async () => { + expect(extractStrategies(`onMedia('(min-width: 768px)')`)).to.deep.equal({ + strategyAttribute: `onMedia('(min-width: 768px)')`, + strategyTemplate: `{{0}}`, + strategies: [{ type: 'onMedia', resolveAble: false, options: '(min-width: 768px)' }], + }); + }); + + it('and', async () => { + expect(extractStrategies(`onVisible && onMedia('(min-width: 768px)')`)).to.deep.equal({ + strategyAttribute: `onVisible && onMedia('(min-width: 768px)')`, + strategyTemplate: `{{0}} && {{1}}`, + strategies: [ + { type: 'onVisible', resolveAble: false }, + { type: 'onMedia', resolveAble: false, options: '(min-width: 768px)' }, + ], + }); + }); + + it('or', async () => { + // desktop: hydrate always + // mobile: hydrate as it becomes visible + expect(extractStrategies(`onVisible || onMedia('(min-width: 768px)')`)).to.deep.equal({ + strategyAttribute: `onVisible || onMedia('(min-width: 768px)')`, + strategyTemplate: `{{0}} || {{1}}`, + strategies: [ + { type: 'onVisible', resolveAble: false }, + { type: 'onMedia', resolveAble: false, options: '(min-width: 768px)' }, + ], + }); + }); + + it('and + or', async () => { + // desktop: hydrate as it becomes visible + // mobile: hydrate on click + expect( + extractStrategies(`onVisible && onMedia('(min-width: 768px)') || onClick`), + ).to.deep.equal({ + strategyAttribute: `onVisible && onMedia('(min-width: 768px)') || onClick`, + strategyTemplate: `{{0}} && {{1}} || {{2}}`, + strategies: [ + { type: 'onVisible', resolveAble: false }, + { type: 'onMedia', resolveAble: false, options: '(min-width: 768px)' }, + { type: 'onClick', resolveAble: false }, + ], + }); + }); + }); + + describe('evaluate', () => { + it('single false', async () => { + expect( + evaluate({ + strategyTemplate: '{{0}}', + strategies: [{ type: 'onClick', resolveAble: false }], + }), + ).to.be.false; + }); + + it('single true', async () => { + expect( + evaluate({ + strategyTemplate: '{{0}}', + strategies: [{ type: 'onClick', resolveAble: true }], + }), + ).to.be.true; + }); + + it('and', async () => { + expect( + evaluate({ + strategyTemplate: `{{0}} && {{1}}`, + strategies: [ + { type: 'onVisible', resolveAble: false }, + { type: 'onMedia', resolveAble: false }, + ], + }), + ).to.be.false; + + expect( + evaluate({ + strategyTemplate: `{{0}} && {{1}}`, + strategies: [ + { type: 'onVisible', resolveAble: true }, + { type: 'onMedia', resolveAble: false }, + ], + }), + ).to.be.false; + + expect( + evaluate({ + strategyTemplate: `{{0}} && {{1}}`, + strategies: [ + { type: 'onVisible', resolveAble: true }, + { type: 'onMedia', resolveAble: true }, + ], + }), + ).to.be.true; + }); + + it('or', async () => { + expect( + evaluate({ + strategyTemplate: `{{0}} || {{1}}`, + strategies: [ + { type: 'onVisible', resolveAble: false }, + { type: 'onMedia', resolveAble: false }, + ], + }), + ).to.be.false; + + expect( + evaluate({ + strategyTemplate: `{{0}} || {{1}}`, + strategies: [ + { type: 'onVisible', resolveAble: false }, + { type: 'onMedia', resolveAble: true }, + ], + }), + ).to.be.true; + }); + + it('and + or', async () => { + expect( + evaluate({ + strategyTemplate: `{{0}} && {{1}} || {{2}}`, + strategies: [ + { type: 'onVisible', resolveAble: false }, + { type: 'onMedia', resolveAble: false }, + { type: 'onClick', resolveAble: true }, + ], + }), + ).to.be.true; + + expect( + evaluate({ + strategyTemplate: `{{0}} && {{1}} || {{2}}`, + strategies: [ + { type: 'onVisible', resolveAble: true }, + { type: 'onMedia', resolveAble: true }, + { type: 'onClick', resolveAble: false }, + ], + }), + ).to.be.true; + + expect( + evaluate({ + strategyTemplate: `{{0}} && {{1}} || {{2}}`, + strategies: [ + { type: 'onVisible', resolveAble: true }, + { type: 'onMedia', resolveAble: false }, + { type: 'onClick', resolveAble: false }, + ], + }), + ).to.be.false; + }); + }); + + describe('validateComponentImportString', () => { + it('allows bare modules', async () => { + expect(validateComponentImportString('@my-pkg/el/MyEl.js::MyEl')).to.be.true; + expect(validateComponentImportString('my-pkg/MyEl.js::MyEl')).to.be.true; + }); + + it('allows private imports', async () => { + expect(validateComponentImportString('#my-private-import/MyEl.js::MyEl')).to.be.true; + }); + + it('allows urls', async () => { + expect(validateComponentImportString('https://domain.com/my-pkg/MyEl.js::MyEl')).to.be.true; + expect(validateComponentImportString('//domain.com/my-pkg/MyEl.js::MyEl')).to.be.true; + }); + + it('disallows relative paths', async () => { + expect(validateComponentImportString('../MyEl.js::MyEl')).to.be.false; + expect(validateComponentImportString('./MyEl.js::MyEl')).to.be.false; + }); + }); +}); diff --git a/packages/engine/test-node/14b-components-files.test.js b/packages/engine/test-node/14b-components-files.test.js new file mode 100644 index 00000000..b35c1523 --- /dev/null +++ b/packages/engine/test-node/14b-components-files.test.js @@ -0,0 +1,487 @@ +import chai from 'chai'; +import { setupTestEngine } from './test-helpers.js'; + +const { expect } = chai; + +describe('Components', () => { + it('01: registers components server side by default', async () => { + const { build, readOutput, readSource, outputExists } = await setupTestEngine( + 'fixtures/14-components/01-load-server-side/docs', + ); + await build(); + + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('@test/components').then(m => m.MyEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + + expect(readOutput('index.html')).to.equal( + [ + // + '', + ].join('\n'), + ); + + expect(outputExists('index-loader-generated.js')).to.be.false; + }); + + it('02: registers components to hydrate on server side', async () => { + const { build, readOutput, readSource } = await setupTestEngine( + 'fixtures/14-components/02-register-hydrate/docs', + ); + await build(); + + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // hydrate-able components', + " customElements.define('my-el', await import('@test/components').then(m => m.MyEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + + expect(readOutput('index.html')).to.equal( + [ + // + '', + '', + ].join('\n'), + ); + + expect(readOutput('index-loader-generated.js')).to.equal( + [ + "import { HydrationLoader } from '@rocket/engine/hydration';", + '', + 'const hydrateAbleComponents = {', + " 'my-el': () => import('@test/components').then(m => m.MyEl),", + '};', + '', + 'const loader = new HydrationLoader(hydrateAbleComponents);', + '', + 'window.__ROCKET_HYDRATION_LOADER__ = loader;', + 'await loader.init();', + ].join('\n'), + ); + }); + + it('03: registers client rendering component', async () => { + const { build, readOutput, readSource } = await setupTestEngine( + 'fixtures/14-components/03-register-client/docs', + ); + await build(); + + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // client-only components', + " // 'my-el2': () => import('@test/components').then(m => m.MyEl2),", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + + expect(readOutput('index.html')).to.equal( + [ + // + '', + '', + ].join('\n'), + ); + + expect(readOutput('index-loader-generated.js')).to.equal( + [ + "import { HydrationLoader } from '@rocket/engine/hydration';", + '', + 'const hydrateAbleComponents = {};', + '', + 'const loader = new HydrationLoader(hydrateAbleComponents);', + '// client-only components', + 'await loader.setup();', + "customElements.define('my-el2', await import('@test/components').then(m => m.MyEl2));", + '', + 'window.__ROCKET_HYDRATION_LOADER__ = loader;', + 'await loader.init();', + ].join('\n'), + ); + }); + + it('04: handles client and hydration at the same time', async () => { + const { build, readOutput } = await setupTestEngine( + 'fixtures/14-components/04-hydration-and-client/docs', + ); + await build(); + + expect(readOutput('index-loader-generated.js')).to.equal( + [ + "import { HydrationLoader } from '@rocket/engine/hydration';", + '', + 'const hydrateAbleComponents = {', + " 'my-el4': () => import('@test/components/MyEl4').then(m => m.MyEl4),", + '};', + '', + 'const loader = new HydrationLoader(hydrateAbleComponents);', + '// client-only components', + 'await loader.setup();', + "customElements.define('my-only', await import('@test/components/MyOnly').then(m => m.MyOnly));", + '', + 'window.__ROCKET_HYDRATION_LOADER__ = loader;', + 'await loader.init();', + ].join('\n'), + ); + }); + + it('05: handles define import error', async () => { + const { build, readOutput, writeSource, readSource } = await setupTestEngine( + 'fixtures/14-components/05-handles-define-import-error/docs', + ); + await writeSource( + 'index.rocket.js', + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.md';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + '// server-only components', + "customElements.define('my-el', await import('../src/MyEl.js').then(m => m.MyEl));", + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + + try { + await build(); + } catch (err) { + expect(err.message).to.contain("Cannot find package 'wrong-pkg'"); + } + + expect(readOutput('index.html')).to.contain("Cannot find package 'wrong-pkg'"); + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('wrong-pkg').then(m => m.WrongClass));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + }); + + it('06: handles define import error in md', async () => { + const { build, readOutput, writeSource, readSource } = await setupTestEngine( + 'fixtures/14-components/06-handles-define-import-error-md/docs', + ); + await writeSource( + 'index.rocket.md', + [ + '```js server', + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.md';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + '// server-only components', + "customElements.define('my-el', await import('../src/MyEl.js').then(m => m.MyEl));", + '/* END - Rocket auto generated - do not touch */', + '```', + '', + '', + ].join('\n'), + ); + + try { + await build(); + } catch (err) { + expect(err.message).to.contain("Cannot find package 'wrong-pkg'"); + } + + expect(readOutput('index.html')).to.contain("Cannot find package 'wrong-pkg'"); + + expect(readSource('index.rocket.md')).to.equal( + [ + '```js server', + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.md';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('wrong-pkg').then(m => m.WrongClass));", + '}', + '/* END - Rocket auto generated - do not touch */', + '```', + '', + '', + ].join('\n'), + ); + }); + + it('07: removes unused elements from registration header', async () => { + const { build, readOutput, readSource, writeSource } = await setupTestEngine( + 'fixtures/14-components/07-removes-registrations/docs', + ); + + await writeSource( + 'index.rocket.js', + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('@test/components').then(m => m.MyEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html`

Hey

`;', + ].join('\n'), + ); + + await build(); + + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html`

Hey

`;', + ].join('\n'), + ); + expect(readOutput('index.html')).to.equal('

Hey

'); + }); + + it('08: do not inject the component loader into open graph layouts', async () => { + const { build, readOutput, readSource, outputExists } = await setupTestEngine( + 'fixtures/14-components/08-open-graph-no-loader-injection/docs', + ); + await build(); + + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components, openGraphServerComponents, openGraphLayout } from './recursive.data.js';", + 'export { html, components, openGraphServerComponents, openGraphLayout };', + 'export async function registerCustomElements() {', + ' // hydrate-able components', + " customElements.define('my-el', await import('@test/components').then(m => m.MyEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + + expect(readOutput('index.html')).to.equal( + [ + '', + '', + ].join('\n'), + ); + expect(readOutput('index.opengraph.html')).to.equal( + [ + '', + '', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + '', + ].join('\n'), + ); + + expect(outputExists('index-loader-generated.js')).to.be.true; + }); + + it('09: the open graph layout can bring additional server side components', async () => { + const { build, readOutput, readSource } = await setupTestEngine( + 'fixtures/14-components/09-open-graph-additional-server-components/docs', + ); + await build(); + + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components, openGraphLayout } from './recursive.data.js';", + 'export { html, components, openGraphLayout };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('@test/components').then(m => m.MyEl));", + ' // server-only open-graph only components', + " customElements.define('other-el', await import('@test/components').then(m => m.OtherEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + + expect(readOutput('index.html')).to.equal( + [''].join( + '\n', + ), + ); + + expect(readOutput('index.opengraph.html')).to.equal( + [ + '', + '', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + ' ', + '', + ].join('\n'), + ); + }); + + it('10: during start it injects/removes the loader script as hydration/client components are added/removed', async () => { + const { writeSource, cleanup, engine, anEngineEvent, readOutput, adjustSource } = + await setupTestEngine('fixtures/14-components/10-start-inject-remove-loader/docs'); + await writeSource('index.rocket.js', 'export default () => html`

init

`;'); + + await engine.start(); + + // add client component => need loader script + await adjustSource('index.rocket.js', /

init<\/p>/, ''); + await anEngineEvent('rocketUpdated'); + expect(readOutput('index.html')).to.equal( + [ + '', + '', + ].join('\n'), + ); + + // remove client component => remove loader script + await adjustSource('index.rocket.js', / loading="client"/, ''); + await anEngineEvent('rocketUpdated'); + expect(readOutput('index.html')).to.equal( + [''].join( + '\n', + ), + ); + + await cleanup(); + }); + + it('11: during start it corrects a wrong rocket header', async () => { + const { writeSource, cleanup, engine, anEngineEvent, readOutput, adjustSource } = + await setupTestEngine('fixtures/14-components/11-start-correct-wrong-header/docs'); + await writeSource( + 'index.rocket.js', + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('#components').then(m => m.MyEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + + await engine.start(); + + await adjustSource('index.rocket.js', /<\/my-el>/, ' '); + await anEngineEvent('rocketUpdated'); + expect(readOutput('index.html')).to.equal( + [''].join( + '\n', + ), + ); + + await cleanup(); + }); + + it('12: during build it corrects a wrong rocket header', async () => { + const { build, writeSource, readSource } = await setupTestEngine( + 'fixtures/14-components/12-build-correct-wrong-header/docs', + ); + await writeSource( + 'index.rocket.js', + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('#components').then(m => m.MyEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + await build(); + + expect(readSource('index.rocket.js')).to.equal( + [ + '/* START - Rocket auto generated - do not touch */', + "export const sourceRelativeFilePath = 'index.rocket.js';", + "import { html, components } from './recursive.data.js';", + 'export { html, components };', + 'export async function registerCustomElements() {', + ' // server-only components', + " customElements.define('my-el', await import('@test/components').then(m => m.MyEl));", + '}', + '/* END - Rocket auto generated - do not touch */', + '', + 'export default () => html``;', + ].join('\n'), + ); + }); +}); diff --git a/packages/engine/test-node/14c-components-e2e.spec.js b/packages/engine/test-node/14c-components-e2e.spec.js new file mode 100644 index 00000000..df19b72f --- /dev/null +++ b/packages/engine/test-node/14c-components-e2e.spec.js @@ -0,0 +1,189 @@ +import { test, expect } from '@playwright/test'; +import { setupTestEngine } from './test-helpers.js'; + +test.describe('hydration', async () => { + test('50: hydrate onClientLoad', async ({ page }) => { + const { engine, cleanup } = await setupTestEngine( + 'fixtures/14-components/50-hydration-onClientLoad/docs', + ); + await engine.start(); + const { port } = engine.devServer.config; + + await page.goto(`localhost:${port}`); + + const myEl = page.locator('my-el'); + const hydrated1 = await myEl.getAttribute('hydrated'); + expect(hydrated1).toBe(null); // not hydrated + + await page.waitForLoadState('networkidle0'); + + const hydrated2 = await myEl.getAttribute('hydrated'); + expect(hydrated2).toBe(''); // boolean attribute is there + + await cleanup(); + }); + + test('51: hydrate onClick', async ({ page }) => { + const { engine, cleanup } = await setupTestEngine( + 'fixtures/14-components/51-hydration-onClick/docs', + ); + await engine.start(); + const { port } = engine.devServer.config; + + await page.goto(`localhost:${port}`); + + const myEl = await page.locator('my-el'); + const hydrated1 = await myEl.getAttribute('hydrated'); + expect(hydrated1).toBe(null); // not hydrated + + await myEl.click(); + await page.waitForLoadState('networkidle0'); + + const hydrated2 = await myEl.getAttribute('hydrated'); + expect(hydrated2).toBe(''); // boolean attribute is there + + await cleanup(); + }); + + test('52: hydrate onVisible', async ({ page }) => { + const { engine, cleanup } = await setupTestEngine( + 'fixtures/14-components/52-hydration-onVisible/docs', + ); + await engine.start(); + const { port } = engine.devServer.config; + + await page.goto(`localhost:${port}`); + const myEl = await page.locator('my-el'); + const hydrated1 = await myEl.getAttribute('hydrated'); + expect(hydrated1).toBe(null); // not hydrated + + await myEl.scrollIntoViewIfNeeded(); + await page.waitForLoadState('networkidle0'); + + const hydrated2 = await myEl.getAttribute('hydrated'); + expect(hydrated2).toBe(''); // boolean attribute is there + + await cleanup(); + }); + + test("53: hydrate onMedia('(max-width: 320px)')", async ({ page }) => { + const { engine, cleanup } = await setupTestEngine( + 'fixtures/14-components/53-hydration-onMedia/docs', + ); + await engine.start(); + const { port } = engine.devServer.config; + + await page.setViewportSize({ + width: 640, + height: 480, + }); + await page.goto(`localhost:${port}`); + const myEl = await page.locator('my-el'); + const hydrated1 = await myEl.getAttribute('hydrated'); + expect(hydrated1).toBe(null); // not hydrated + + await page.setViewportSize({ + width: 320, + height: 480, + }); + await page.waitForLoadState('networkidle0'); + + const hydrated2 = await myEl.getAttribute('hydrated'); + expect(hydrated2).toBe(''); // boolean attribute is there + + await cleanup(); + }); + + test("53b: hydrate onMedia('(max-width: 320px)') as initial size", async ({ page }) => { + const { engine, cleanup } = await setupTestEngine( + 'fixtures/14-components/53-hydration-onMedia/docs', + ); + await engine.start(); + const { port } = engine.devServer.config; + + await page.setViewportSize({ + width: 320, + height: 480, + }); + await page.goto(`localhost:${port}`); + const myEl = await page.locator('my-el'); + await page.waitForLoadState('networkidle0'); + + const hydrated2 = await myEl.getAttribute('hydrated'); + expect(hydrated2).toBe(''); // boolean attribute is there + + await cleanup(); + }); + + test("54: hydrate onMedia('(max-width: 320px)') && onClick", async ({ page }) => { + const { engine, cleanup } = await setupTestEngine( + 'fixtures/14-components/54-hydration-onMedia-onClick/docs', + ); + await engine.start(); + const { port } = engine.devServer.config; + + await page.setViewportSize({ + width: 640, + height: 480, + }); + await page.goto(`localhost:${port}`); + const myEl = await page.locator('my-el'); + await myEl.click(); + await page.waitForLoadState('networkidle0'); + const hydrated1 = await myEl.getAttribute('hydrated'); + expect(hydrated1).toBe(null); // not hydrated + + await page.setViewportSize({ + width: 320, + height: 480, + }); + await myEl.click(); + await page.waitForTimeout(100); // TODO: why is this timeout needed? + await page.waitForLoadState('networkidle0'); + + const hydrated2 = await myEl.getAttribute('hydrated'); + expect(hydrated2).toBe(''); // boolean attribute is there + + await cleanup(); + }); + + test("55: hydrate onMedia('(min-width: 640px)') || onClick", async ({ page }) => { + const { engine, cleanup } = await setupTestEngine( + 'fixtures/14-components/55-hydration-onMedia-or-onClick/docs', + ); + await engine.start(); + const { port } = engine.devServer.config; + + await page.setViewportSize({ + width: 640, + height: 480, + }); + await page.goto(`localhost:${port}`); + const myEl = await page.locator('my-el'); + const hydrated1 = await myEl.getAttribute('hydrated'); + expect(hydrated1).toBe(null); // not hydrated + + await page.waitForLoadState('networkidle0'); + + const hydrated2 = await myEl.getAttribute('hydrated'); + expect(hydrated2).toBe(''); // boolean attribute is there + + // revisit page on "mobile" + await page.setViewportSize({ + width: 320, + height: 480, + }); + await page.reload(); + const myEl2 = await page.locator('my-el'); + const hydrated3 = await myEl2.getAttribute('hydrated'); + expect(hydrated3).toBe(null); // not hydrated + + await myEl.click(); + await page.waitForLoadState('networkidle0'); + + const hydrated4 = await myEl2.getAttribute('hydrated'); + expect(hydrated4).toBe(''); // boolean attribute is there + + await cleanup(); + }); +}); diff --git a/packages/engine/test-node/fixtures/06-error-handling/01-page-error/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/06-error-handling/01-page-error/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..4f081f50 --- /dev/null +++ b/packages/engine/test-node/fixtures/06-error-handling/01-page-error/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,10 @@ +{ + "title": "foo is not defined", + "h1": "foo is not defined", + "name": "foo is not defined", + "menuLinkText": "foo is not defined", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/09b-watch-error-handling/03-markdown/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/09b-watch-error-handling/03-markdown/docs/pageTreeData.rocketGenerated.json index e003a42c..f5ce0509 100644 --- a/packages/engine/test-node/fixtures/09b-watch-error-handling/03-markdown/docs/pageTreeData.rocketGenerated.json +++ b/packages/engine/test-node/fixtures/09b-watch-error-handling/03-markdown/docs/pageTreeData.rocketGenerated.json @@ -13,5 +13,6 @@ "outputRelativeFilePath": "index.html", "sourceRelativeFilePath": "index.rocket.md", "level": 0, - "foo": "bar" + "foo": "bar", + "title": "Unexpected token 'const'" } \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/package.json b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/package.json new file mode 100644 index 00000000..8f5eebc6 --- /dev/null +++ b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyVeryLongElementName.js" + } +} diff --git a/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/index.rocket.js b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/index.rocket.js new file mode 100644 index 00000000..ba40f7c0 --- /dev/null +++ b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/index.rocket.js @@ -0,0 +1,17 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +// prettier-ignore +import { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components } from './local.data.js'; +// prettier-ignore +export { veryLongFileHeaderValue, multipleLongFileHeaderValues, fakeHtml, fakeComponents, fakeLayout, components }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('my-el', await import('@test/components').then(m => m.MyVeryLongElementName)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => ` + This will be a very long line that will explain a complex topic in multiple paragraphs. The level of detail is important. + +`; diff --git a/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/local.data.js b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/local.data.js new file mode 100644 index 00000000..a04f58a9 --- /dev/null +++ b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/local.data.js @@ -0,0 +1,9 @@ +export const veryLongFileHeaderValue = 1; +export const multipleLongFileHeaderValues = 2; +export const fakeHtml = ''; +export const fakeComponents = ''; +export const fakeLayout = ''; + +export const components = { + 'my-el': '@test/components::MyVeryLongElementName', +}; diff --git a/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..2e73376b --- /dev/null +++ b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/pages/pageTreeData.rocketGenerated.json @@ -0,0 +1,13 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "fakeComponents": "", + "fakeHtml": "", + "fakeLayout": "", + "multipleLongFileHeaderValues": 2, + "veryLongFileHeaderValue": 1 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/src/MyVeryLongElementName.js b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/src/MyVeryLongElementName.js new file mode 100644 index 00000000..5f2fc91d --- /dev/null +++ b/packages/engine/test-node/fixtures/13-config/03-long-file-header-comment/src/MyVeryLongElementName.js @@ -0,0 +1,29 @@ +import { LitElement, html, css } from 'lit'; + +export class MyVeryLongElementName extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } + + static styles = css` + :host([hydrated]) { + background: green; + display: block; + } + `; +} diff --git a/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.js new file mode 100644 index 00000000..53dae03d --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // server-only components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.md b/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.md deleted file mode 100644 index 72b3a68f..00000000 --- a/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/index.rocket.md +++ /dev/null @@ -1,9 +0,0 @@ -```js server -/* START - Rocket auto generated - do not touch */ -export const sourceRelativeFilePath = 'index.rocket.md'; -import { components } from './recursive.data.js'; -export { components }; -/* END - Rocket auto generated - do not touch */ -``` - - diff --git a/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/pageTreeData.rocketGenerated.json index b36acbaf..929b8fca 100644 --- a/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/pageTreeData.rocketGenerated.json +++ b/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/pageTreeData.rocketGenerated.json @@ -1,8 +1,8 @@ { - "name": "index.rocket.md", - "menuLinkText": "index.rocket.md", + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", "url": "/", "outputRelativeFilePath": "index.html", - "sourceRelativeFilePath": "index.rocket.md", + "sourceRelativeFilePath": "index.rocket.js", "level": 0 } \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/recursive.data.js index 9c25760f..8762e030 100644 --- a/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/recursive.data.js +++ b/packages/engine/test-node/fixtures/14-components/01-load-server-side/docs/recursive.data.js @@ -1,3 +1,5 @@ +export { html } from 'lit'; + export const components = { - 'my-el': () => import(new URL('../src/MyEl.js', import.meta.url)).then(m => m.MyEl), + 'my-el': '@test/components::MyEl', }; diff --git a/packages/engine/test-node/fixtures/14-components/01-load-server-side/package.json b/packages/engine/test-node/fixtures/14-components/01-load-server-side/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/01-load-server-side/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/index.rocket.js new file mode 100644 index 00000000..8178fb1a --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/recursive.data.js new file mode 100644 index 00000000..8762e030 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el': '@test/components::MyEl', +}; diff --git a/packages/engine/test-node/fixtures/14-components/02-register-hydrate/package.json b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/02-register-hydrate/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/02-register-hydrate/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/03-register-client/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/03-register-client/docs/index.rocket.js new file mode 100644 index 00000000..27a92b81 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/03-register-client/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // client-only components + // 'my-el2': () => import('@test/components').then(m => m.MyEl2), +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/03-register-client/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/03-register-client/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/03-register-client/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/03-register-client/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/03-register-client/docs/recursive.data.js new file mode 100644 index 00000000..c8859516 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/03-register-client/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el2': '@test/components::MyEl2', +}; diff --git a/packages/engine/test-node/fixtures/14-components/03-register-client/package.json b/packages/engine/test-node/fixtures/14-components/03-register-client/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/03-register-client/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/03-register-client/src/MyEl2.js b/packages/engine/test-node/fixtures/14-components/03-register-client/src/MyEl2.js new file mode 100644 index 00000000..41c96025 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/03-register-client/src/MyEl2.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl2 extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/index.rocket.js new file mode 100644 index 00000000..5ab1454c --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/index.rocket.js @@ -0,0 +1,16 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el4', await import('@test/components/MyEl4').then(m => m.MyEl4)); + // client-only components + // 'my-only': () => import('@test/components/MyOnly').then(m => m.MyOnly), +} +/* END - Rocket auto generated - do not touch */ + +export default () => html` + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/recursive.data.js new file mode 100644 index 00000000..6830ced4 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/docs/recursive.data.js @@ -0,0 +1,6 @@ +export { html } from 'lit'; + +export const components = { + 'my-el4': '@test/components/MyEl4::MyEl4', + 'my-only': '@test/components/MyOnly::MyOnly', +}; diff --git a/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/package.json b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/package.json new file mode 100644 index 00000000..a7ab680c --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + "./*": "./src/*.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyEl4.js b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyEl4.js new file mode 100644 index 00000000..35e73b5e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyEl4.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl4 extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyOnly.js b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyOnly.js new file mode 100644 index 00000000..b7b07fdf --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/04-hydration-and-client/src/MyOnly.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyOnly extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/index.rocket.js new file mode 100644 index 00000000..814ec148 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // server-only components + customElements.define('my-el', await import('wrong-pkg').then(m => m.WrongClass)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/recursive.data.js new file mode 100644 index 00000000..9f3c2c20 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el': 'wrong-pkg::WrongClass', +}; diff --git a/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/package.json b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/05-handles-define-import-error/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/index.rocket.md b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/index.rocket.md new file mode 100644 index 00000000..fc69cdf2 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/index.rocket.md @@ -0,0 +1,13 @@ +```js server +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.md'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // server-only components + customElements.define('my-el', await import('wrong-pkg').then(m => m.WrongClass)); +} +/* END - Rocket auto generated - do not touch */ +``` + + diff --git a/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..b36acbaf --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.md", + "menuLinkText": "index.rocket.md", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.md", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/recursive.data.js new file mode 100644 index 00000000..9f3c2c20 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el': 'wrong-pkg::WrongClass', +}; diff --git a/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/package.json b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/06-handles-define-import-error-md/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/index.rocket.js new file mode 100644 index 00000000..8286fa0e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/index.rocket.js @@ -0,0 +1,7 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +/* END - Rocket auto generated - do not touch */ + +export default () => html`

Hey

`; diff --git a/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/recursive.data.js new file mode 100644 index 00000000..8762e030 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el': '@test/components::MyEl', +}; diff --git a/packages/engine/test-node/fixtures/14-components/07-removes-registrations/package.json b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/07-removes-registrations/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..bfa648c1 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "docs/index.rocket.js", + "menuLinkText": "docs/index.rocket.js", + "url": "/docs/", + "outputRelativeFilePath": "docs/index.html", + "sourceRelativeFilePath": "docs/index.rocket.js", + "level": 1 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/07-removes-registrations/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/07-removes-registrations/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/index.rocket.js new file mode 100644 index 00000000..42748d00 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, openGraphServerComponents, openGraphLayout } from './recursive.data.js'; +export { html, components, openGraphServerComponents, openGraphLayout }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/recursive.data.js new file mode 100644 index 00000000..cd99d314 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/docs/recursive.data.js @@ -0,0 +1,21 @@ +import { html } from 'lit'; + +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', +}; + +export const openGraphServerComponents = { ...components }; + +export const openGraphLayout = () => html` + + + + + + + + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/package.json b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..bfa648c1 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "docs/index.rocket.js", + "menuLinkText": "docs/index.rocket.js", + "url": "/docs/", + "outputRelativeFilePath": "docs/index.html", + "sourceRelativeFilePath": "docs/index.rocket.js", + "level": 1 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/08-open-graph-no-loader-injection/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/index.rocket.js new file mode 100644 index 00000000..2062b1fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/index.rocket.js @@ -0,0 +1,13 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, openGraphLayout } from './recursive.data.js'; +export { html, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); + // server-only open-graph only components + customElements.define('other-el', await import('@test/components').then(m => m.OtherEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/recursive.data.js new file mode 100644 index 00000000..b2c4a8ee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/docs/recursive.data.js @@ -0,0 +1,22 @@ +import { html } from 'lit'; + +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', + 'other-el': '@test/components::OtherEl', + 'next-el': '@test/components::NextEl', +}; + +export const openGraphLayout = () => html` + + + + + + + + + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/package.json b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/package.json new file mode 100644 index 00000000..9aa9f62e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/index.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..bfa648c1 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "docs/index.rocket.js", + "menuLinkText": "docs/index.rocket.js", + "url": "/docs/", + "outputRelativeFilePath": "docs/index.html", + "sourceRelativeFilePath": "docs/index.rocket.js", + "level": 1 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/NextEl.js b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/NextEl.js new file mode 100644 index 00000000..c1b1d299 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/NextEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class NextEl extends LitElement { + render() { + return html`

Other Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/OtherEl.js b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/OtherEl.js new file mode 100644 index 00000000..ddbe2516 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/OtherEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class OtherEl extends LitElement { + render() { + return html`

Other Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/index.js b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/index.js new file mode 100644 index 00000000..9f8eaef1 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/09-open-graph-additional-server-components/src/index.js @@ -0,0 +1,2 @@ +export { MyEl } from './MyEl.js'; +export { OtherEl } from './OtherEl.js'; diff --git a/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/index.rocket.js new file mode 100644 index 00000000..53dae03d --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // server-only components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/recursive.data.js new file mode 100644 index 00000000..8762e030 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el': '@test/components::MyEl', +}; diff --git a/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/package.json b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/10-start-inject-remove-loader/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/index.rocket.js new file mode 100644 index 00000000..f71912b2 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // server-only components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html` `; diff --git a/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..c387c447 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,10 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "title": "Package import specifier \"#components\" is not defined in package /Users/ff67qn/html/rocket/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/package.json imported from /Users/ff67qn/html/rocket/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/index.rocket.js", + "h1": "Package import specifier \"#components\" is not defined in package /Users/ff67qn/html/rocket/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/package.json imported from /Users/ff67qn/html/rocket/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/index.rocket.js" +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/recursive.data.js new file mode 100644 index 00000000..8762e030 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el': '@test/components::MyEl', +}; diff --git a/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/package.json b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/11-start-correct-wrong-header/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/index.rocket.js new file mode 100644 index 00000000..53dae03d --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components } from './recursive.data.js'; +export { html, components }; +export async function registerCustomElements() { + // server-only components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..929b8fca --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,8 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0 +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/recursive.data.js new file mode 100644 index 00000000..8762e030 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/docs/recursive.data.js @@ -0,0 +1,5 @@ +export { html } from 'lit'; + +export const components = { + 'my-el': '@test/components::MyEl', +}; diff --git a/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/package.json b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/src/MyEl.js new file mode 100644 index 00000000..d2cb42fb --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/12-build-correct-wrong-header/src/MyEl.js @@ -0,0 +1,7 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/index.rocket.js new file mode 100644 index 00000000..b98fb27b --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, layout } from './recursive.data.js'; +export { html, components, layout }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..39006edc --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,11 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "components": { + "my-el": "() => import('@test/components').then(m => m.MyEl)" + } +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/recursive.data.js new file mode 100644 index 00000000..1d74836e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/docs/recursive.data.js @@ -0,0 +1,15 @@ +import { html } from 'lit'; +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', +}; + +export const layout = data => html` + + + + ${data.content()} + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/package.json b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/src/MyEl.js new file mode 100644 index 00000000..4ed103e7 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/50-hydration-onClientLoad/src/MyEl.js @@ -0,0 +1,22 @@ +import { LitElement, html } from 'lit'; + +export class MyEl extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } +} diff --git a/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/index.rocket.js new file mode 100644 index 00000000..a025f80e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, layout } from './recursive.data.js'; +export { html, components, layout }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html``; diff --git a/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..39006edc --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,11 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "components": { + "my-el": "() => import('@test/components').then(m => m.MyEl)" + } +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/recursive.data.js new file mode 100644 index 00000000..1d74836e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/docs/recursive.data.js @@ -0,0 +1,15 @@ +import { html } from 'lit'; +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', +}; + +export const layout = data => html` + + + + ${data.content()} + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/package.json b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/src/MyEl.js new file mode 100644 index 00000000..d16bb781 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/51-hydration-onClick/src/MyEl.js @@ -0,0 +1,29 @@ +import { LitElement, html, css } from 'lit'; + +export class MyEl extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } + + static styles = css` + :host([hydrated]) { + background: green; + display: block; + } + `; +} diff --git a/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/index.rocket.js new file mode 100644 index 00000000..8cab8db8 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/index.rocket.js @@ -0,0 +1,14 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, layout } from './recursive.data.js'; +export { html, components, layout }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html` +

+ +`; diff --git a/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..39006edc --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,11 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "components": { + "my-el": "() => import('@test/components').then(m => m.MyEl)" + } +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/recursive.data.js new file mode 100644 index 00000000..1d74836e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/docs/recursive.data.js @@ -0,0 +1,15 @@ +import { html } from 'lit'; +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', +}; + +export const layout = data => html` + + + + ${data.content()} + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/package.json b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/src/MyEl.js new file mode 100644 index 00000000..d16bb781 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/52-hydration-onVisible/src/MyEl.js @@ -0,0 +1,29 @@ +import { LitElement, html, css } from 'lit'; + +export class MyEl extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } + + static styles = css` + :host([hydrated]) { + background: green; + display: block; + } + `; +} diff --git a/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/index.rocket.js new file mode 100644 index 00000000..4d0fee6c --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/index.rocket.js @@ -0,0 +1,11 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, layout } from './recursive.data.js'; +export { html, components, layout }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html` `; diff --git a/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..39006edc --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,11 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "components": { + "my-el": "() => import('@test/components').then(m => m.MyEl)" + } +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/recursive.data.js new file mode 100644 index 00000000..1d74836e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/docs/recursive.data.js @@ -0,0 +1,15 @@ +import { html } from 'lit'; +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', +}; + +export const layout = data => html` + + + + ${data.content()} + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/package.json b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/src/MyEl.js new file mode 100644 index 00000000..d16bb781 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/53-hydration-onMedia/src/MyEl.js @@ -0,0 +1,29 @@ +import { LitElement, html, css } from 'lit'; + +export class MyEl extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } + + static styles = css` + :host([hydrated]) { + background: green; + display: block; + } + `; +} diff --git a/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/index.rocket.js new file mode 100644 index 00000000..a1a571f1 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/index.rocket.js @@ -0,0 +1,13 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, layout } from './recursive.data.js'; +export { html, components, layout }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html` + +`; diff --git a/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..39006edc --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,11 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "components": { + "my-el": "() => import('@test/components').then(m => m.MyEl)" + } +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/recursive.data.js new file mode 100644 index 00000000..1d74836e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/docs/recursive.data.js @@ -0,0 +1,15 @@ +import { html } from 'lit'; +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', +}; + +export const layout = data => html` + + + + ${data.content()} + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/package.json b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/src/MyEl.js new file mode 100644 index 00000000..d16bb781 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/54-hydration-onMedia-onClick/src/MyEl.js @@ -0,0 +1,29 @@ +import { LitElement, html, css } from 'lit'; + +export class MyEl extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } + + static styles = css` + :host([hydrated]) { + background: green; + display: block; + } + `; +} diff --git a/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/index.rocket.js b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/index.rocket.js new file mode 100644 index 00000000..6f7b882a --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/index.rocket.js @@ -0,0 +1,13 @@ +/* START - Rocket auto generated - do not touch */ +export const sourceRelativeFilePath = 'index.rocket.js'; +import { html, components, layout } from './recursive.data.js'; +export { html, components, layout }; +export async function registerCustomElements() { + // hydrate-able components + customElements.define('my-el', await import('@test/components').then(m => m.MyEl)); +} +/* END - Rocket auto generated - do not touch */ + +export default () => html` + +`; diff --git a/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/pageTreeData.rocketGenerated.json b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/pageTreeData.rocketGenerated.json new file mode 100644 index 00000000..39006edc --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/pageTreeData.rocketGenerated.json @@ -0,0 +1,11 @@ +{ + "name": "index.rocket.js", + "menuLinkText": "index.rocket.js", + "url": "/", + "outputRelativeFilePath": "index.html", + "sourceRelativeFilePath": "index.rocket.js", + "level": 0, + "components": { + "my-el": "() => import('@test/components').then(m => m.MyEl)" + } +} \ No newline at end of file diff --git a/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/recursive.data.js b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/recursive.data.js new file mode 100644 index 00000000..1d74836e --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/docs/recursive.data.js @@ -0,0 +1,15 @@ +import { html } from 'lit'; +export { html }; + +export const components = { + 'my-el': '@test/components::MyEl', +}; + +export const layout = data => html` + + + + ${data.content()} + + +`; diff --git a/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/package.json b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/package.json new file mode 100644 index 00000000..158febee --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/package.json @@ -0,0 +1,7 @@ +{ + "name": "@test/components", + "type": "module", + "exports": { + ".": "./src/MyEl.js" + } +} diff --git a/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/src/MyEl.js b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/src/MyEl.js new file mode 100644 index 00000000..d16bb781 --- /dev/null +++ b/packages/engine/test-node/fixtures/14-components/55-hydration-onMedia-or-onClick/src/MyEl.js @@ -0,0 +1,29 @@ +import { LitElement, html, css } from 'lit'; + +export class MyEl extends LitElement { + static properties = { + msg: { type: String }, + hydrated: { type: Boolean, reflect: true }, + }; + + constructor() { + super(); + this.hydrated = false; + } + + updated(props) { + super.updated(props); + this.hydrated = true; + } + + render() { + return html`

Hello World

`; + } + + static styles = css` + :host([hydrated]) { + background: green; + display: block; + } + `; +} diff --git a/packages/engine/test-node/test-helpers.js b/packages/engine/test-node/test-helpers.js index c55b02d0..5de9e515 100644 --- a/packages/engine/test-node/test-helpers.js +++ b/packages/engine/test-node/test-helpers.js @@ -68,7 +68,12 @@ function formatFn(text, { format = 'html', removeEndNewLine = false } = {}) { return text; } - let formatted = prettier.format(text, { parser: useFormat, printWidth: 100, singleQuote: true }); + let formatted = prettier.format(text, { + parser: useFormat, + printWidth: 100, + singleQuote: true, + arrowParens: 'avoid', + }); // remove all empty lines for html if (useFormat === 'html') { @@ -156,6 +161,12 @@ export async function setupTestEngine(docsDir, options = {}) { await writeFile(filePath, text); } + async function adjustSource(relPath, regex, replace) { + const content = readSource(relPath); + const newContent = content.replace(regex, replace); + await writeSource(relPath, newContent); + } + async function deleteSource(toInspect) { const filePath = path.join(engine.docsDir, toInspect); await rm(filePath, { force: true, recursive: true }); @@ -222,5 +233,6 @@ export async function setupTestEngine(docsDir, options = {}) { anEngineEvent, setAsOpenedInBrowser, renameSource, + adjustSource, }; } diff --git a/packages/engine/types/main.d.ts b/packages/engine/types/main.d.ts index a7424c11..1381d6fd 100644 --- a/packages/engine/types/main.d.ts +++ b/packages/engine/types/main.d.ts @@ -8,15 +8,17 @@ export interface EngineOptions { watchDir: string; open: boolean; clearOutputDir: boolean; - plugins: EnginePlugin[]; + plugins?: EnginePlugin[]; defaultPlugins: MetaPluginOfEngine[]; setupPlugins: MetaPluginOfEngine[]; renderMode: 'development' | 'production'; + longFileHeaderWidth: number; + longFileHeaderComment: string; devServerPlugins: DevServerPlugin[]; setupDevServerPlugins: any[]; setupDevServerMiddleware: any[]; - adjustDevServerOptions: (options: DevServerConfig) => DevServerConfig; + adjustDevServerOptions?: (options: DevServerConfig) => DevServerConfig; } export class EnginePlugin { @@ -37,4 +39,36 @@ export interface renderWorkerResult { sourceRelativeFilePath: string; keepConvertedFiles: boolean; passOnError?: Error; + componentStrings: ComponentStrings; + openGraphHtml: string; +} + +export interface Components { + [key: string]: () => Promise; +} + +export interface ComponentStrings { + [key: string]: string; +} + +export interface Strategy { + type: string; + resolveAble: boolean; + options?: string; +} + +export interface LoadingStrategy { + strategyAttribute: string; + strategies: Strategy[]; + strategyTemplate: string; +} + +interface PotentialLitElement extends Element { + updateComplete?: Promise; +} + +export interface ElementWithStrategy extends LoadingStrategy { + tagName: string; + node: PotentialLitElement; + deleteMe?: boolean; } diff --git a/packages/launch/src/LayoutSidebar.js b/packages/launch/src/LayoutSidebar.js index 1fb3795e..b56b6ab6 100644 --- a/packages/launch/src/LayoutSidebar.js +++ b/packages/launch/src/LayoutSidebar.js @@ -256,7 +256,6 @@ export class LayoutSidebar extends Layout { `, bottom__50: html` - `, @@ -271,19 +270,19 @@ export class LayoutSidebar extends Layout { return nothing; }, - bottom__70: () => html` - - `, + // bottom__70: () => html` + // + // `, }; } @@ -291,7 +290,7 @@ export class LayoutSidebar extends Layout { return html`
- + diff --git a/packages/mdjs-preview/package.json b/packages/mdjs-preview/package.json index 6b5db8f4..cf0aafaa 100644 --- a/packages/mdjs-preview/package.json +++ b/packages/mdjs-preview/package.json @@ -33,7 +33,7 @@ "src" ], "dependencies": { - "@lion/accordion": "^0.7.2", + "@lion/accordion": "^0.9.0", "@open-wc/scoped-elements": "^2.0.0", "lit": "^2.0.0" }, diff --git a/packages/search/package.json b/packages/search/package.json index 762852d7..56be4c67 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -46,9 +46,9 @@ "search" ], "dependencies": { - "@lion/combobox": "^0.8.6", - "@lion/core": "^0.19.0", - "@lion/listbox": "^0.10.7", + "@lion/combobox": "^0.10.0", + "@lion/core": "^0.22.0", + "@lion/listbox": "^0.13.0", "@open-wc/scoped-elements": "^2.0.0", "@rocket/engine": "^0.1.0-alpha.22", "minisearch": "^3.0.2", diff --git a/packages/search/src/RocketCliSearch.js b/packages/search/src/RocketCliSearch.js index 448f6ff6..dcc3544b 100644 --- a/packages/search/src/RocketCliSearch.js +++ b/packages/search/src/RocketCliSearch.js @@ -1,4 +1,6 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ + +// @ts-ignore https://github.com/lucaong/minisearch/issues/152 import MiniSearch from 'minisearch'; import { getIdBlocksOfHtml } from './getIdBlocksOfHtml.js'; // import readline from 'readline'; diff --git a/packages/search/src/index.components.js b/packages/search/src/index.components.js index 6f9cc298..d31e3308 100644 --- a/packages/search/src/index.components.js +++ b/packages/search/src/index.components.js @@ -1,3 +1,3 @@ export const searchComponents = { - // 'rocket-search': () => import('./RocketSearch.js').then(m => m.RocketSearch), + 'rocket-search': '@rocket/search/web::RocketSearch', }; diff --git a/patches/@web+dev-server+0.1.29.patch b/patches/@web+dev-server+0.1.29.patch deleted file mode 100644 index 76fc6e91..00000000 --- a/patches/@web+dev-server+0.1.29.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/node_modules/@web/dev-server/package.json b/node_modules/@web/dev-server/package.json -index d8b7697..883ba22 100644 ---- a/node_modules/@web/dev-server/package.json -+++ b/node_modules/@web/dev-server/package.json -@@ -20,6 +20,7 @@ - }, - "exports": { - ".": { -+ "types": "./index.d.ts", - "import": "./index.mjs", - "require": "./dist/index.js" - } diff --git a/patches/@web+dev-server-core+0.3.17.patch b/patches/@web+dev-server-core+0.3.17.patch deleted file mode 100644 index bee6293c..00000000 --- a/patches/@web+dev-server-core+0.3.17.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/node_modules/@web/dev-server-core/package.json b/node_modules/@web/dev-server-core/package.json -index 1b06565..d7fc12a 100644 ---- a/node_modules/@web/dev-server-core/package.json -+++ b/node_modules/@web/dev-server-core/package.json -@@ -16,6 +16,7 @@ - "main": "dist/index.js", - "exports": { - ".": { -+ "types": "./index.d.ts", - "import": "./index.mjs", - "require": "./dist/index.js" - }, diff --git a/patches/es-module-lexer+0.9.3.patch b/patches/es-module-lexer+0.9.3.patch deleted file mode 100644 index 5eb6ff7d..00000000 --- a/patches/es-module-lexer+0.9.3.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/node_modules/es-module-lexer/package.json b/node_modules/es-module-lexer/package.json -index bdabf21..3ca5b1e 100644 ---- a/node_modules/es-module-lexer/package.json -+++ b/node_modules/es-module-lexer/package.json -@@ -7,6 +7,7 @@ - "types": "types/lexer.d.ts", - "exports": { - ".": { -+ "types": "./types/lexer.d.ts", - "module": "./dist/lexer.js", - "import": "./dist/lexer.js", - "require": "./dist/lexer.cjs" diff --git a/presets/spark/package.json b/presets/spark/package.json index e679766e..27b34365 100644 --- a/presets/spark/package.json +++ b/presets/spark/package.json @@ -24,6 +24,10 @@ "types": "./dist-types/src/index.components.d.ts", "default": "./src/index.components.js" }, + "./components/*": { + "types": "./dist-types/src/*.d.ts", + "default": "./src/*.js" + }, "./css/*": "./src/css/*.css" }, "scripts": { diff --git a/presets/spark/src/index.components.js b/presets/spark/src/index.components.js index 3990cbf8..aef54043 100644 --- a/presets/spark/src/index.components.js +++ b/presets/spark/src/index.components.js @@ -1,4 +1,4 @@ export const sparkComponents = { - 'block-blue': () => import('./BlockBlue.js').then(m => m.BlockBlue), - 'block-features': () => import('./BlockFeatures.js').then(m => m.BlockFeatures), + 'block-blue': '@rocket/spark/components/BlockBlue::BlockBlue', + 'block-features': '@rocket/spark/components/BlockFeatures::BlockFeatures', }; diff --git a/site/pages/10--docs/10--setup/10--getting-started.rocket.md b/site/pages/10--docs/10--setup/10--getting-started.rocket.md index c6c9eae1..b54ec76b 100644 --- a/site/pages/10--docs/10--setup/10--getting-started.rocket.md +++ b/site/pages/10--docs/10--setup/10--getting-started.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/10--setup/10--getting-started.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const subTitle = 'Create your first Rocket site'; diff --git a/site/pages/10--docs/10--setup/20--adding-pages.rocket.md b/site/pages/10--docs/10--setup/20--adding-pages.rocket.md index 8b4994e4..86a5535e 100644 --- a/site/pages/10--docs/10--setup/20--adding-pages.rocket.md +++ b/site/pages/10--docs/10--setup/20--adding-pages.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/10--setup/20--adding-pages.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/10--setup/30--use-javascript.rocket.md b/site/pages/10--docs/10--setup/30--use-javascript.rocket.md index 46dd41be..5d7f96c7 100644 --- a/site/pages/10--docs/10--setup/30--use-javascript.rocket.md +++ b/site/pages/10--docs/10--setup/30--use-javascript.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/10--setup/30--use-javascript.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/10--setup/index.rocket.js b/site/pages/10--docs/10--setup/index.rocket.js index 43b08e84..6a1bd2ee 100644 --- a/site/pages/10--docs/10--setup/index.rocket.js +++ b/site/pages/10--docs/10--setup/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/10--setup/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/10--docs/20--basics/10--project-structure.rocket.md b/site/pages/10--docs/20--basics/10--project-structure.rocket.md index e82f80b6..ea65774a 100644 --- a/site/pages/10--docs/20--basics/10--project-structure.rocket.md +++ b/site/pages/10--docs/20--basics/10--project-structure.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/10--project-structure.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const description = 'Learn how to structure a project with Rocket.'; diff --git a/site/pages/10--docs/20--basics/20--pages.rocket.md b/site/pages/10--docs/20--basics/20--pages.rocket.md index f45be132..2bd445b1 100644 --- a/site/pages/10--docs/20--basics/20--pages.rocket.md +++ b/site/pages/10--docs/20--basics/20--pages.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/20--pages.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const description = `An intro to Rocket pages, which is the actual website content.`; diff --git a/site/pages/10--docs/20--basics/30--data-cascade.rocket.md b/site/pages/10--docs/20--basics/30--data-cascade.rocket.md index f8fe4774..39d78fd2 100644 --- a/site/pages/10--docs/20--basics/30--data-cascade.rocket.md +++ b/site/pages/10--docs/20--basics/30--data-cascade.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/30--data-cascade.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/20--basics/40--components.rocket.md b/site/pages/10--docs/20--basics/40--components.rocket.md index b0adc481..34a30b0f 100644 --- a/site/pages/10--docs/20--basics/40--components.rocket.md +++ b/site/pages/10--docs/20--basics/40--components.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/40--components.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` @@ -175,12 +178,11 @@ First we need to adjust our component file - customElements.define('rocket-greeting', RocketGreeting); ``` -And then in our page we can export `components` with a function that dynamically loads the component. +And then in our page we can export `components` where we define tag name, a "globally" working import and the class name. ```js export const components = { - 'rocket-greeting': () => - import('../src/components/RocketGreeting.js').then(m => m.RocketGreeting), + 'rocket-greeting': 'my-pkg/src/components/RocketGreeting.js::RocketGreeting', }; ``` @@ -194,8 +196,7 @@ import { sparkComponents } from '@rocket/spark/components'; export const components = { ...rocketComponents, ...sparkComponents, - 'rocket-greeting': () => - import('../src/components/RocketGreeting.js').then(m => m.RocketGreeting), + 'rocket-greeting': 'my-pkg/src/components/RocketGreeting.js::RocketGreeting', }; ``` @@ -210,11 +211,22 @@ Let me repeat that: - Rocket will handle **if and when the loading and registration should happen**. Be it client or server side or both in a very specific timing via hydration. - Rocket will only load the components that are actually used which means that `components` can be a huge list without any performance impact. - +Site level components are implemented in the same way as the [Data Cascade](./30--data-cascade.rocket.md) e.g. by injecting those components into your file header. +This means that we know all the components and where they are from by looking at the file header. -Not yet fully implemented - currently all components are always loaded server side. Join the [GitHub](https://github.com/modernweb-dev/rocket/issues/308) discussion. +It may look something like this - +```js +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // hydrate-able components + customElements.define('my-counter', await import('#components/MyCounter').then(m => m.MyCounter)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), +} +``` If we wish to disable or override a component then we can do so via @@ -225,7 +237,7 @@ import { components as originalComponents } from '../path/to/recursive.data.js'; export const components = { ...originalComponents, // keep all the original components 'rocket-greeting': false, // no automatic handling of this component - 'other-component': () => MyOtherComponent, // override the default component + 'other-component': 'my-pkg/src/components/OverrideOther.js::OverrideOther', // override the default component }; ``` @@ -237,7 +249,7 @@ All other component should be handled via the `components` object to enable hand Doing so enables hydration based on attributes on the component. ```html - + ``` See the [Hydration Docs](./80--hydration.rocket.md) for more information. diff --git a/site/pages/10--docs/20--basics/50--layouts.rocket.md b/site/pages/10--docs/20--basics/50--layouts.rocket.md index 31e86087..8c4bcee0 100644 --- a/site/pages/10--docs/20--basics/50--layouts.rocket.md +++ b/site/pages/10--docs/20--basics/50--layouts.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/50--layouts.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/20--basics/60--routing.rocket.md b/site/pages/10--docs/20--basics/60--routing.rocket.md index cf711145..96d7490b 100644 --- a/site/pages/10--docs/20--basics/60--routing.rocket.md +++ b/site/pages/10--docs/20--basics/60--routing.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/60--routing.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/20--basics/70--navigation.rocket.md b/site/pages/10--docs/20--basics/70--navigation.rocket.md index 18dbce51..f693905b 100644 --- a/site/pages/10--docs/20--basics/70--navigation.rocket.md +++ b/site/pages/10--docs/20--basics/70--navigation.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/70--navigation.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/20--basics/80--hydration.rocket.md b/site/pages/10--docs/20--basics/80--hydration.rocket.md index 2d51586f..63afdffa 100644 --- a/site/pages/10--docs/20--basics/80--hydration.rocket.md +++ b/site/pages/10--docs/20--basics/80--hydration.rocket.md @@ -1,19 +1,262 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/80--hydration.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // hydrate-able components + customElements.define('my-counter', await import('#components/MyCounter').then(m => m.MyCounter)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` # Hydration -This feature is not yet implemented. +By default all components are only rendered on the server. +This however means those components are "static" and can not add interactivity. -Be sure to join the discussion on [GitHub](https://github.com/modernweb-dev/rocket/issues/308). +To add interactivity to your component you can either render it only on the client or you can render on the server and `hydrate` it on the client. + +## Progressive Hydration + +With Rocket we recommend to use progressive Hydration. + +You can see it as
+➡️ Start with 0 JavaScript
+➡️ Load JavaScript of components as needed + +In practice this means we use components without any loading strategy if we want server rendering. +For a static site like a blog this will be almost all of my components. +But some components will have interactivity and those will need to be hydrated. + +In the following example we have two components being only server rendered and one being hydrated. + +```html + +

Here is more text

+ + + +``` + +- If this is the only content on the page it means it will load with zero JavaScript 🎉. +- If we use the sign up then the JS of `blog-newsletter-sign-up` will be loaded to give feedback about a valid email address. +- If we don't then no additional JS will be loaded at all. + + + +The automatic loading/hydration only works if you [register components to the rocket loader](./40--components.rocket.md). + + + +## Server Loading + +Server Loading has almost zero impact on the client side page performance and is therefore fastest possible solution available. + +Loading and rendering on the server is the default and for that reasons does not need to be specified. + +```html + +``` + +will result in a server rendering only. + +The output will be a [Declarative Shadow Dom (DSD)](https://web.dev/declarative-shadow-dom/). + +```html + + + +``` + +which looks like this + +
+ + + +
+ +Open it on [Codepen](https://codepen.io/daKmoR/pen/qBpQVGK) to play around. + +A DSD does not need any JavaScript (in 2022: none chromium browser need a polyfill) to display elements with their styles scoped. + +If possible you should always render your component only on the server to avoid unnecessary JavaScript. +This results in the best possible site performance. + +Server only rendered components however can never be interactive. For interactive components you need JavaScript which you can bring by using progressive hydration. + +## Hydration Loading + +Hydration Loading roughly has a medium impact on the client side page performance. For the initial load there is almost zero impact and we then decide when to take the performance hit by loading and executing the JavaScript of components. + +Hydration Loading becomes necessary as soon as we need interactive components. +In Rocket we recommend to progressively hydrate based on user actions. + +For example a counter only server rendered will not work as expected. + +```html + + +``` + +👇 the +/- buttons will not do anything + +
+ +
+ +To "enable" it we set the `loading` attribute for example to `hydrate:onClick`. + +```html + +``` + +👇 now if we click the +/- buttons the component will hydrate and the counter works + +
+ +
+ + + +After you clicked on the 2nd example the 1st example will start working as well. +The reason for that is that it's the same component `my-counter`. +Once you hydrate a component it will hydrate all its instances. + + + +### Hydration Conditions + +You can specify and combine multiple conditions on when to hydrate a component. + +```html + +``` + +| Option | Description | +| ------------------------------ | --------------------------------------------------------------------------------------- | +| onClientLoad | as soon as possible | +| onClick | as you click on the element | +| onMedia | as soon as a media query is met | +| onVisible | as soon as component + optional padding becomes visible | +| onHover (⚠️ not implemented) | as you hover over the element + optional padding (click triggers hover => touchscreens) | +| withIdle (⚠️ not implemented) | as soon there is a free slot in the main thread | +| withDelay (⚠️ not implemented) | after x ms | + +Each of the options can be combined via `&&` or `||`. + +| Example | Description | +| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | +| `onClientLoad` | above the fold element that should become interactive as soon as possible | +| `onMedia('(max-width: 320px)')` | mobile burger menu that triggers a drawer for navigation (only hydrate on screens smaller then 320p) | +| `onMedia('(min-width: 640px)') && onClick` | chart that only becomes interactive on desktop after a click | +| `onMedia('(prefers-reduced-motion: no-preference)') && onClick` | a visual animation that plays on click only if there is no prefers-reduced-motion | +| `onVisible` | heavy chart that becomes interactive when element becomes visible | +| `onVisible(100px)` | heavy chart that becomes interactive when element + 100px padding becomes visible | + + + +Hydration Loading does not (yet) support passing complex SSR data via properties. e.g. components that want to hydrate can only use attributes for now. + + + +## Client Loading + +Client Loading has a large impact on the client side page performance. +It means nothing happens on the server and the JavaScript for the component gets shipped and instantly executed to render the "initial" paint of the component. + +HTML with components using client loading is shipped as is. + +```html + +``` + +As the HTML does not contain any details of the content within `my-el` it also means that SEO might be impacted. + +When will we still use Client Loading? + +- Components that can not be server rendered + - Technical reasons like usage of `canvas` or `webgl` which can not be "rendered" into HTML + - Components may do things that hit some of the SSR limitation + - SSR Limitations means to only do imperative manipulation of the DOM in `update, updated, firstUpdated` for more see [lit-ssr docs](https://github.com/lit/lit/tree/main/packages/labs/ssr#notes-and-limitations) + - Web Components SSR is pretty new so some components may need adjustments before they can work with SSR +- Components that require user data do not make sense to SSR if using Build Time SSR. + +## Loading Strategy Impacts + +Which loading strategy you choose will have an impact on the performance of your page. +The higher the impact the more JavaScript you send to the client which will result in lower performance. + +If you use a component on the same page with different loading strategies then the following impacts applies + +1. client (high impact) +2. hydrate (medium impact) +3. server (low impact) + +The loading strategy with the highest impact will be applied to all components. + +```html + + + +``` + +Results in `client rendering` of all `my-component`s. + + +```html + + +``` + + +Results in `server+hydration rendering` of all `my-component`s. + + +```html + + +``` + + +Results in `server rendering` of all `my-component`s. + +Why theses impacts? + +1. client - if you eagerly load & render the component on the client then bloating the html of some components by server rendering does not bring any benefit +2. hydrate - hydration means that all component with the same tag name will be hydrated on the client - you can not keep a server only variation of a component +3. server - almost zero client side impact + + + +Always try to load all components of a page with the same (lowest) impact if possible. + + diff --git a/site/pages/10--docs/20--basics/90--assets.rocket.md b/site/pages/10--docs/20--basics/90--assets.rocket.md index 5ad8c9e1..b491ef91 100644 --- a/site/pages/10--docs/20--basics/90--assets.rocket.md +++ b/site/pages/10--docs/20--basics/90--assets.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/90--assets.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/20--basics/95--configuration.rocket.md b/site/pages/10--docs/20--basics/95--configuration.rocket.md index 000c1040..98282fa1 100644 --- a/site/pages/10--docs/20--basics/95--configuration.rocket.md +++ b/site/pages/10--docs/20--basics/95--configuration.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/95--configuration.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/20--basics/index.rocket.js b/site/pages/10--docs/20--basics/index.rocket.js index 1517d007..97a216c0 100644 --- a/site/pages/10--docs/20--basics/index.rocket.js +++ b/site/pages/10--docs/20--basics/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/20--basics/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/10--docs/30--guides/20--social-media.rocket.md b/site/pages/10--docs/30--guides/20--social-media.rocket.md index 86b9b856..1f14e691 100644 --- a/site/pages/10--docs/30--guides/20--social-media.rocket.md +++ b/site/pages/10--docs/30--guides/20--social-media.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/20--social-media.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const description = diff --git a/site/pages/10--docs/30--guides/30--images.rocket.md b/site/pages/10--docs/30--guides/30--images.rocket.md index 5c05d97a..df4f1f10 100644 --- a/site/pages/10--docs/30--guides/30--images.rocket.md +++ b/site/pages/10--docs/30--guides/30--images.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/30--images.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/30--guides/40--markdown.rocket.md b/site/pages/10--docs/30--guides/40--markdown.rocket.md index 4a51a865..43af83af 100644 --- a/site/pages/10--docs/30--guides/40--markdown.rocket.md +++ b/site/pages/10--docs/30--guides/40--markdown.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/40--markdown.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/30--guides/50--go-live.rocket.md b/site/pages/10--docs/30--guides/50--go-live.rocket.md index 684c9234..c337d8a3 100644 --- a/site/pages/10--docs/30--guides/50--go-live.rocket.md +++ b/site/pages/10--docs/30--guides/50--go-live.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/50--go-live.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { inlineFile } from '@rocket/engine'; diff --git a/site/pages/10--docs/30--guides/60--cross-browser.rocket.md b/site/pages/10--docs/30--guides/60--cross-browser.rocket.md index 93d122be..0b2d2f07 100644 --- a/site/pages/10--docs/30--guides/60--cross-browser.rocket.md +++ b/site/pages/10--docs/30--guides/60--cross-browser.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/60--cross-browser.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { inlineFile } from '@rocket/engine'; diff --git a/site/pages/10--docs/30--guides/70--styles-and-css.rocket.md b/site/pages/10--docs/30--guides/70--styles-and-css.rocket.md index c0ddc2ea..9746c508 100644 --- a/site/pages/10--docs/30--guides/70--styles-and-css.rocket.md +++ b/site/pages/10--docs/30--guides/70--styles-and-css.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/70--styles-and-css.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/30--guides/80--web-fonts.rocket.md b/site/pages/10--docs/30--guides/80--web-fonts.rocket.md index 0dc7bc33..6f5177b2 100644 --- a/site/pages/10--docs/30--guides/80--web-fonts.rocket.md +++ b/site/pages/10--docs/30--guides/80--web-fonts.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/80--web-fonts.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const description = diff --git a/site/pages/10--docs/30--guides/90--data-fetching.rocket.md b/site/pages/10--docs/30--guides/90--data-fetching.rocket.md index 1d8a6942..df077fbd 100644 --- a/site/pages/10--docs/30--guides/90--data-fetching.rocket.md +++ b/site/pages/10--docs/30--guides/90--data-fetching.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/90--data-fetching.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/30--guides/95--deploy.rocket.md b/site/pages/10--docs/30--guides/95--deploy.rocket.md index 3066e769..6950fde6 100644 --- a/site/pages/10--docs/30--guides/95--deploy.rocket.md +++ b/site/pages/10--docs/30--guides/95--deploy.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/95--deploy.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/10--docs/30--guides/index.rocket.js b/site/pages/10--docs/30--guides/index.rocket.js index 7574e201..930a2c35 100644 --- a/site/pages/10--docs/30--guides/index.rocket.js +++ b/site/pages/10--docs/30--guides/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/30--guides/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/10--docs/index.rocket.md b/site/pages/10--docs/index.rocket.md index 597f58f3..53f5f491 100644 --- a/site/pages/10--docs/index.rocket.md +++ b/site/pages/10--docs/index.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '10--docs/index.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { pageTree } from '../__shared/pageTree.js'; diff --git a/site/pages/20--presets/10--components/10--overview.rocket.md b/site/pages/20--presets/10--components/10--overview.rocket.md index aacc22de..e00f5cbd 100644 --- a/site/pages/20--presets/10--components/10--overview.rocket.md +++ b/site/pages/20--presets/10--components/10--overview.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/10--components/10--overview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/20--presets/10--components/card-icon.rocket.md b/site/pages/20--presets/10--components/card-icon.rocket.md index 674e0ce8..781c6d37 100644 --- a/site/pages/20--presets/10--components/card-icon.rocket.md +++ b/site/pages/20--presets/10--components/card-icon.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/10--components/card-icon.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('card-icon', await import('@rocket/components/components/CardIcon').then(m => m.CardIcon)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { CardIcon } from '@rocket/components/server'; diff --git a/site/pages/20--presets/10--components/index.rocket.js b/site/pages/20--presets/10--components/index.rocket.js index 435c4ddc..5fcd73c2 100644 --- a/site/pages/20--presets/10--components/index.rocket.js +++ b/site/pages/20--presets/10--components/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/10--components/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/20--presets/10--components/inline-notification.rocket.md b/site/pages/20--presets/10--components/inline-notification.rocket.md index ed8209e1..465b0f7c 100644 --- a/site/pages/20--presets/10--components/inline-notification.rocket.md +++ b/site/pages/20--presets/10--components/inline-notification.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/10--components/inline-notification.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { InlineNotification } from '@rocket/components'; diff --git a/site/pages/20--presets/20--launch/10--overview.rocket.md b/site/pages/20--presets/20--launch/10--overview.rocket.md index 0ce4c176..923d49a4 100644 --- a/site/pages/20--presets/20--launch/10--overview.rocket.md +++ b/site/pages/20--presets/20--launch/10--overview.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/20--launch/10--overview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/20--presets/20--launch/20--service-worker.rocket.md b/site/pages/20--presets/20--launch/20--service-worker.rocket.md index fb6b719d..ca4ab2e3 100644 --- a/site/pages/20--presets/20--launch/20--service-worker.rocket.md +++ b/site/pages/20--presets/20--launch/20--service-worker.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/20--launch/20--service-worker.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { inlineFile } from '@rocket/engine'; diff --git a/site/pages/20--presets/20--launch/index.rocket.js b/site/pages/20--presets/20--launch/index.rocket.js index 093e8405..5ee9079b 100644 --- a/site/pages/20--presets/20--launch/index.rocket.js +++ b/site/pages/20--presets/20--launch/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/20--launch/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/20--presets/30--spark/10--overview.rocket.md b/site/pages/20--presets/30--spark/10--overview.rocket.md index f9203d1f..b4968724 100644 --- a/site/pages/20--presets/30--spark/10--overview.rocket.md +++ b/site/pages/20--presets/30--spark/10--overview.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/30--spark/10--overview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/20--presets/30--spark/20--demo.rocket.js b/site/pages/20--presets/30--spark/20--demo.rocket.js index bdbee346..cf91356c 100644 --- a/site/pages/20--presets/30--spark/20--demo.rocket.js +++ b/site/pages/20--presets/30--spark/20--demo.rocket.js @@ -1,12 +1,27 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/30--spark/20--demo.rocket.js'; -import { - html, - setupUnifiedPlugins, - components as originalComponents, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, setupUnifiedPlugins, components as originalComponents, openGraphLayout } from '../../recursive.data.js'; export { html, setupUnifiedPlugins, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('permanent-notification', await import('@rocket/components/components/PermanentNotification').then(m => m.PermanentNotification)); + // prettier-ignore + customElements.define('block-columns', await import('@rocket/components/components/BlockColumns').then(m => m.BlockColumns)); + // prettier-ignore + customElements.define('card-icon', await import('@rocket/components/components/CardIcon').then(m => m.CardIcon)); + // prettier-ignore + customElements.define('feature-small', await import('@rocket/components/components/FeatureSmall').then(m => m.FeatureSmall)); + // prettier-ignore + customElements.define('block-features', await import('@rocket/spark/components/BlockFeatures').then(m => m.BlockFeatures)); + // prettier-ignore + customElements.define('testimonial-small', await import('@rocket/components/components/TestimonialSmall').then(m => m.TestimonialSmall)); + // prettier-ignore + customElements.define('block-blue', await import('@rocket/spark/components/BlockBlue').then(m => m.BlockBlue)); + // prettier-ignore + customElements.define('the-block', await import('@rocket/components/components/TheBlock').then(m => m.TheBlock)); +} /* END - Rocket auto generated - do not touch */ export const menuLinkText = 'Demo'; diff --git a/site/pages/20--presets/30--spark/index.rocket.js b/site/pages/20--presets/30--spark/index.rocket.js index 56624fad..28155425 100644 --- a/site/pages/20--presets/30--spark/index.rocket.js +++ b/site/pages/20--presets/30--spark/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/30--spark/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/20--presets/index.rocket.md b/site/pages/20--presets/index.rocket.md index 5ffa898f..895fd6ed 100644 --- a/site/pages/20--presets/index.rocket.md +++ b/site/pages/20--presets/index.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '20--presets/index.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { pageTree } from '../__shared/pageTree.js'; diff --git a/site/pages/30--tools/10--plugins-manager/10--overview.rocket.md b/site/pages/30--tools/10--plugins-manager/10--overview.rocket.md index 68f5a5af..018d7e92 100644 --- a/site/pages/30--tools/10--plugins-manager/10--overview.rocket.md +++ b/site/pages/30--tools/10--plugins-manager/10--overview.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/10--plugins-manager/10--overview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/30--tools/10--plugins-manager/index.rocket.js b/site/pages/30--tools/10--plugins-manager/index.rocket.js index 941fc0a0..ef7ab457 100644 --- a/site/pages/30--tools/10--plugins-manager/index.rocket.js +++ b/site/pages/30--tools/10--plugins-manager/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/10--plugins-manager/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/30--tools/20--markdown-javascript/10--overview.rocket.md b/site/pages/30--tools/20--markdown-javascript/10--overview.rocket.md index f26c26c4..b2e4d0d1 100644 --- a/site/pages/30--tools/20--markdown-javascript/10--overview.rocket.md +++ b/site/pages/30--tools/20--markdown-javascript/10--overview.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/20--markdown-javascript/10--overview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/30--tools/20--markdown-javascript/20--preview.rocket.md b/site/pages/30--tools/20--markdown-javascript/20--preview.rocket.md index 3bf97148..0bc7a023 100644 --- a/site/pages/30--tools/20--markdown-javascript/20--preview.rocket.md +++ b/site/pages/30--tools/20--markdown-javascript/20--preview.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/20--markdown-javascript/20--preview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/30--tools/20--markdown-javascript/30--story.rocket.md b/site/pages/30--tools/20--markdown-javascript/30--story.rocket.md index 10dde835..0af6f358 100644 --- a/site/pages/30--tools/20--markdown-javascript/30--story.rocket.md +++ b/site/pages/30--tools/20--markdown-javascript/30--story.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/20--markdown-javascript/30--story.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/30--tools/20--markdown-javascript/index.rocket.js b/site/pages/30--tools/20--markdown-javascript/index.rocket.js index 790bec74..36491db8 100644 --- a/site/pages/30--tools/20--markdown-javascript/index.rocket.js +++ b/site/pages/30--tools/20--markdown-javascript/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/20--markdown-javascript/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/30--tools/30--rollup-config/10--overview.rocket.md b/site/pages/30--tools/30--rollup-config/10--overview.rocket.md index 695cb70c..8a6bffb3 100644 --- a/site/pages/30--tools/30--rollup-config/10--overview.rocket.md +++ b/site/pages/30--tools/30--rollup-config/10--overview.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/30--rollup-config/10--overview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/30--tools/30--rollup-config/index.rocket.js b/site/pages/30--tools/30--rollup-config/index.rocket.js index 16625b34..8e108225 100644 --- a/site/pages/30--tools/30--rollup-config/index.rocket.js +++ b/site/pages/30--tools/30--rollup-config/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/30--rollup-config/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/30--tools/40--check-html-links/10--overview.rocket.md b/site/pages/30--tools/40--check-html-links/10--overview.rocket.md index 21f8c8ee..7f9ea5d1 100644 --- a/site/pages/30--tools/40--check-html-links/10--overview.rocket.md +++ b/site/pages/30--tools/40--check-html-links/10--overview.rocket.md @@ -1,14 +1,17 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/40--check-html-links/10--overview.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('inline-notification', await import('@rocket/components/components/InlineNotification').then(m => m.InlineNotification)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ ``` diff --git a/site/pages/30--tools/40--check-html-links/index.rocket.js b/site/pages/30--tools/40--check-html-links/index.rocket.js index 82131bda..7ff1bcbd 100644 --- a/site/pages/30--tools/40--check-html-links/index.rocket.js +++ b/site/pages/30--tools/40--check-html-links/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/40--check-html-links/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuNoLink = true; diff --git a/site/pages/30--tools/index.rocket.md b/site/pages/30--tools/index.rocket.md index 8ba27dca..35717262 100644 --- a/site/pages/30--tools/index.rocket.md +++ b/site/pages/30--tools/index.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '30--tools/index.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ import { pageTree } from '../__shared/pageTree.js'; diff --git a/site/pages/40--blog/001--introducing-check-html-links.rocket.md b/site/pages/40--blog/001--introducing-check-html-links.rocket.md index e49aaa71..73db60ac 100644 --- a/site/pages/40--blog/001--introducing-check-html-links.rocket.md +++ b/site/pages/40--blog/001--introducing-check-html-links.rocket.md @@ -1,14 +1,14 @@ ```js server /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '40--blog/001--introducing-check-html-links.rocket.md'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const tags = ['html', 'javascript', 'webdev', 'node']; diff --git a/site/pages/40--blog/index.rocket.js b/site/pages/40--blog/index.rocket.js index 0d7426e9..5c91c450 100644 --- a/site/pages/40--blog/index.rocket.js +++ b/site/pages/40--blog/index.rocket.js @@ -1,13 +1,13 @@ /* START - Rocket auto generated - do not touch */ export const sourceRelativeFilePath = '40--blog/index.rocket.js'; -import { - html, - layout, - setupUnifiedPlugins, - components, - openGraphLayout, -} from '../recursive.data.js'; +// prettier-ignore +import { html, layout, setupUnifiedPlugins, components, openGraphLayout } from '../recursive.data.js'; export { html, layout, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), + // 'rocket-drawer': () => import('@rocket/drawer').then(m => m.RocketDrawer), +} /* END - Rocket auto generated - do not touch */ export const menuLinkText = 'Blog'; diff --git a/site/pages/__shared/search.js b/site/pages/__shared/search.js index a424b9e1..57fc9a41 100644 --- a/site/pages/__shared/search.js +++ b/site/pages/__shared/search.js @@ -1,12 +1,11 @@ import { html } from 'lit'; export const search = html` - + - `; diff --git a/site/pages/index.rocket.js b/site/pages/index.rocket.js index ed0a1a9a..beb723ec 100644 --- a/site/pages/index.rocket.js +++ b/site/pages/index.rocket.js @@ -2,6 +2,13 @@ export const sourceRelativeFilePath = 'index.rocket.js'; import { html, setupUnifiedPlugins, components } from './recursive.data.js'; export { html, setupUnifiedPlugins, components }; +export async function registerCustomElements() { + // server-only open-graph only components + // prettier-ignore + customElements.define('card-icon', await import('@rocket/components/components/CardIcon').then(m => m.CardIcon)); + // client-only components + // 'rocket-search': () => import('@rocket/search/web').then(m => m.RocketSearch), +} /* END - Rocket auto generated - do not touch */ import { footerMenu } from './__shared/footerMenu.js'; diff --git a/site/pages/opengraph.rocket.js b/site/pages/opengraph.rocket.js index ae23bfcf..363854ac 100644 --- a/site/pages/opengraph.rocket.js +++ b/site/pages/opengraph.rocket.js @@ -2,6 +2,13 @@ export const sourceRelativeFilePath = 'opengraph.rocket.js'; import { html, setupUnifiedPlugins, components, openGraphLayout } from './recursive.data.js'; export { html, setupUnifiedPlugins, components, openGraphLayout }; +export async function registerCustomElements() { + // server-only components + // prettier-ignore + customElements.define('server-icon', await import('@rocket/components/components/ServerIcon').then(m => m.ServerIcon)); + // prettier-ignore + customElements.define('opengraph-overview', await import('@rocket/components/components/OpenGraphOverview').then(m => m.OpenGraphOverview)); +} /* END - Rocket auto generated - do not touch */ import { pageTree } from '#pageTree'; diff --git a/site/pages/pageTreeData.rocketGenerated.json b/site/pages/pageTreeData.rocketGenerated.json index e64b4d75..8600975f 100644 --- a/site/pages/pageTreeData.rocketGenerated.json +++ b/site/pages/pageTreeData.rocketGenerated.json @@ -453,6 +453,36 @@ "text": "Hydration", "id": "hydration", "level": 1 + }, + { + "text": "Progressive Hydration", + "id": "progressive-hydration", + "level": 2 + }, + { + "text": "Server Loading", + "id": "server-loading", + "level": 2 + }, + { + "text": "Hydration Loading", + "id": "hydration-loading", + "level": 2 + }, + { + "text": "Hydration Conditions", + "id": "hydration-conditions", + "level": 3 + }, + { + "text": "Client Loading", + "id": "client-loading", + "level": 2 + }, + { + "text": "Loading Strategy Impacts", + "id": "loading-strategy-impacts", + "level": 2 } ], "name": "Hydration", diff --git a/site/pages/recursive.data.js b/site/pages/recursive.data.js index 63fa82ab..0f0c92fe 100644 --- a/site/pages/recursive.data.js +++ b/site/pages/recursive.data.js @@ -65,7 +65,12 @@ export const setupUnifiedPlugins = [ }), ]; -export const components = { ...rocketComponents, ...searchComponents }; +export const components = { + ...rocketComponents, + ...searchComponents, + 'my-counter': '#components/MyCounter::MyCounter', + 'rocket-drawer': '@rocket/drawer::RocketDrawer', +}; export const openGraphLayout = data => html` diff --git a/site/src/components/MyCounter.js b/site/src/components/MyCounter.js new file mode 100644 index 00000000..48f197f3 --- /dev/null +++ b/site/src/components/MyCounter.js @@ -0,0 +1,41 @@ +import { LitElement, css, html } from 'lit'; + +export class MyCounter extends LitElement { + constructor() { + super(); + this.counter = 0; + } + + render() { + return html` + + ${this.counter} + + `; + } + + static styles = css` + * { + font-size: 200%; + } + + span { + width: 4rem; + display: inline-block; + text-align: center; + } + + button { + width: 64px; + height: 64px; + border: none; + border-radius: 10px; + background-color: seagreen; + color: white; + } + `; + + static properties = { + counter: { type: Number }, + }; +} diff --git a/yarn.lock b/yarn.lock index 06f1710f..ac5ff00c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1450,10 +1450,10 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@esm-bundle/chai@^4.3.4": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@esm-bundle/chai/-/chai-4.3.4.tgz#74ed4a0794b3a9f9517ff235744ac6f4be0d34dc" - integrity sha512-6Tx35wWiNw7X0nLY9RMx8v3EL8SacCFW+eEZOE9Hc+XxmU5HFE2AFEg+GehUZpiyDGwVvPH75ckGlqC7coIPnA== +"@esm-bundle/chai@^4.3.4-fix.0": + version "4.3.4-fix.0" + resolved "https://registry.yarnpkg.com/@esm-bundle/chai/-/chai-4.3.4-fix.0.tgz#3084cff7eb46d741749f47f3a48dbbdcbaf30a92" + integrity sha512-26SKdM4uvDWlY8/OOOxSB1AqQWeBosCX3wRYUZO7enTAj03CtVxIiCimYVG2WpULcyV51qapK4qTovwkUr5Mlw== dependencies: "@types/chai" "^4.2.12" @@ -1500,65 +1500,65 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@lion/accordion@^0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@lion/accordion/-/accordion-0.7.2.tgz#c60c149ddca0d2fea826868f209c7e2b12dd9afa" - integrity sha512-oIKizAXwemVDW1rEKXSXT6KZhEJemQuFrUrNhQZPQaDDyb1K05wV8FIfquE0mNyo6xk69+bqv5O2G89nDwfIkQ== +"@lion/accordion@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@lion/accordion/-/accordion-0.9.0.tgz#eafc074c11e928c1bb5af42ba88fc522cecdbb1c" + integrity sha512-ReFron+V7Uvrtuzb8H/qqvALmDJJNJu54uOcHuhU3AZvwZaQhe3q1A2Uo/gs+U4udYv20oeI3dsNPV6GnB+RTg== dependencies: - "@lion/core" "0.19.0" + "@lion/core" "^0.22.0" -"@lion/combobox@^0.8.6": - version "0.8.6" - resolved "https://registry.yarnpkg.com/@lion/combobox/-/combobox-0.8.6.tgz#746028d0cd9f468dfc35cf2dfbdb603367f4e281" - integrity sha512-24hm557YTdwK5/CShfgM6VqQD3uATyghU3JZq9rdzVQl2Ff+Sd2wp4zMEKWtKGnSbWPQNdrCn7kdNv7bF54PVg== +"@lion/combobox@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@lion/combobox/-/combobox-0.10.0.tgz#f3dc4cb719efaf832173ce3afc9d8e5fe90bfaf7" + integrity sha512-Qmd0a+g9mozgz+iSAeAPqQNlXHDCk4Stx1TZAfwHZWG/MKxmY3IO1qQOXvNkLtpeYmJYL1ZeaWxFKK9svEsgzw== dependencies: - "@lion/core" "0.19.0" - "@lion/form-core" "0.15.4" - "@lion/listbox" "0.10.7" - "@lion/overlays" "0.29.1" + "@lion/core" "^0.22.0" + "@lion/form-core" "^0.17.0" + "@lion/listbox" "^0.13.0" + "@lion/overlays" "^0.32.0" -"@lion/core@0.19.0", "@lion/core@^0.19.0": - version "0.19.0" - resolved "https://registry.yarnpkg.com/@lion/core/-/core-0.19.0.tgz#4bf86059acd0ef3f74e6d0689250edc4d6664836" - integrity sha512-SU2JzKEgGdwOVK9WdsmjKiYkgQ/hOYC05jxyHfG9qJWmOzEUsuvvULjwU8hd1u7gLy5gSxsdEO2nJ2zyWV2ihg== +"@lion/core@^0.22.0": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@lion/core/-/core-0.22.0.tgz#a914e7584323a090629e02e51a0e5dc3a9030882" + integrity sha512-qgIRqp77UtMFi9PDxS6EE5xT6djqJ6qWNKur08mnKNNIg9NtVUeGSpSLGuMeZs+lI1To+n9/DrOsbSpJ0xUKIQ== dependencies: "@open-wc/dedupe-mixin" "^1.3.0" - "@open-wc/scoped-elements" "^2.0.1" + "@open-wc/scoped-elements" "^2.1.1" lit "^2.0.2" -"@lion/form-core@0.15.4": - version "0.15.4" - resolved "https://registry.yarnpkg.com/@lion/form-core/-/form-core-0.15.4.tgz#e5fdc49199b9a491becf70370ab6de1407bc7a66" - integrity sha512-QkTl0c1BS2Egd2gTHTnfIfvvv3Ywkh1+6mDfEelIQOoptf84AFGw5OdVoMPqrAk0gYUkm8YvdpTZSzh3mMANiQ== +"@lion/form-core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@lion/form-core/-/form-core-0.17.0.tgz#82011e6a63147c8252c8d611253850cb977ece62" + integrity sha512-YSe/BcbY9TCTlW4Ua3FPUpvXpIrm3nxtPjoPGd6zk6Gg35uUgTxTwlnlA6gBGAiQgod/qdM29KEOzM+KnhWYsg== dependencies: - "@lion/core" "0.19.0" - "@lion/localize" "0.21.3" + "@lion/core" "^0.22.0" + "@lion/localize" "^0.24.0" -"@lion/listbox@0.10.7", "@lion/listbox@^0.10.7": - version "0.10.7" - resolved "https://registry.yarnpkg.com/@lion/listbox/-/listbox-0.10.7.tgz#9af689615ea0964e4a5613c3e5b2df9b33fc2d54" - integrity sha512-hCVWnYsJv/det/+o5LHPd5w3f5mXiRE1q0ZVf+Hat5lvcHiHXfKnlrKaB2DzMqqL9y9k4ZG7feyQZlNE5PLNrQ== +"@lion/listbox@^0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@lion/listbox/-/listbox-0.13.0.tgz#ca606dd4421592a4c041f3595f8bcf24885a7826" + integrity sha512-h8B1o59qyozmToZglre8pzP/xNq1y8bvUG49fTbzpGuauFW++lIWYXhZAxA+dARlbVA4iIw6Jw0xI+0m/SGtqg== dependencies: - "@lion/core" "0.19.0" - "@lion/form-core" "0.15.4" + "@lion/core" "^0.22.0" + "@lion/form-core" "^0.17.0" -"@lion/localize@0.21.3": - version "0.21.3" - resolved "https://registry.yarnpkg.com/@lion/localize/-/localize-0.21.3.tgz#6ed63aa79d4a6df37536d8be8d03d11b855c32b6" - integrity sha512-BXFuKYYM+XABlULS8tLddj1TviRHK0Bm1AR6cOrdStv8vSrTK9szV63c5Ybl+kD6QstBSQ4qNwbjd3hAIJVGhQ== +"@lion/localize@^0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@lion/localize/-/localize-0.24.0.tgz#4c04970645f7e89a6163d2ac563966a974dc0e56" + integrity sha512-LVTiupjMJFHNblJiw2naKWyxw8J8yw7F4ftywbasrYu0ejlGpqWFsI1jINY7oMGGnlgYUPSuu7NFpiyUsOsuvg== dependencies: "@bundled-es-modules/message-format" "6.0.4" - "@lion/core" "0.19.0" - singleton-manager "1.4.2" + "@lion/core" "^0.22.0" + singleton-manager "^1.4.3" -"@lion/overlays@0.29.1", "@lion/overlays@^0.29.1": - version "0.29.1" - resolved "https://registry.yarnpkg.com/@lion/overlays/-/overlays-0.29.1.tgz#0e2cff719d119a89a09cc7adc9baea1579dab022" - integrity sha512-MtoPavlnSVbisPPK+VPOyvekE5STHOH3GubC63danjVbMC9Nf927kzLT19l89JPxseejpU0fXHSdz7PVhNGgIA== +"@lion/overlays@^0.32.0": + version "0.32.0" + resolved "https://registry.yarnpkg.com/@lion/overlays/-/overlays-0.32.0.tgz#d9c7d0bfd7895768efcf9bcc65a97e330bdcf424" + integrity sha512-VyHilarcgWYYM+NDNXxuAiAT8EHipJUHNiaV85OLzwgqqMFC5TsG9wyekqj5iu3mk96R4s/RU1gjqfR9O88INQ== dependencies: - "@lion/core" "0.19.0" + "@lion/core" "^0.22.0" "@popperjs/core" "^2.5.4" - singleton-manager "1.4.2" + singleton-manager "^1.4.3" "@lit-labs/ssr-client@^1.0.0": version "1.0.0" @@ -1655,14 +1655,13 @@ resolved "https://registry.yarnpkg.com/@open-wc/dedupe-mixin/-/dedupe-mixin-1.3.0.tgz#0df5d438285fc3482838786ee81895318f0ff778" integrity sha512-UfdK1MPnR6T7f3svzzYBfu3qBkkZ/KsPhcpc3JYhsUY4hbpwNF9wEQtD4Z+/mRqMTJrKg++YSxIxE0FBhY3RIw== -"@open-wc/scoped-elements@^2.0.0", "@open-wc/scoped-elements@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@open-wc/scoped-elements/-/scoped-elements-2.0.1.tgz#6b1c3535f809bd90710574db80093a81e3a1fc2d" - integrity sha512-JS6ozxUFwFX3+Er91v9yQzNIaFn7OnE0iESKTbFvkkKdNwvAPtp1fpckBKIvWk8Ae9ZcoI9DYZuT2DDbMPcadA== +"@open-wc/scoped-elements@^2.0.0", "@open-wc/scoped-elements@^2.0.1", "@open-wc/scoped-elements@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@open-wc/scoped-elements/-/scoped-elements-2.1.1.tgz#a43a2167d259af1f113301fcc93b1b9a6c371991" + integrity sha512-qQAtVIK2H1oUIM2oSrCBnf1+ZGHd2nIowt1tete+Dn9rNXIogAMJlUBY/R1NR9MuuJvQ1MeFjgQoDmb05TUdkw== dependencies: "@lit/reactive-element" "^1.0.0" "@open-wc/dedupe-mixin" "^1.3.0" - "@webcomponents/scoped-custom-element-registry" "^0.0.3" "@open-wc/semantic-dom-diff@^0.13.16": version "0.13.21" @@ -1677,24 +1676,24 @@ "@types/chai" "^4.2.11" "@web/test-runner-commands" "^0.5.7" -"@open-wc/testing-helpers@^2.0.4": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@open-wc/testing-helpers/-/testing-helpers-2.0.5.tgz#47da17629483760864a9c7cac620d1799ff4b243" - integrity sha512-pqigKSFDdmERXIq8tI6yEclZ1/PwAvbIuW+kA3kqTnxVkcQew+W+Dw31QDarscNKTsDkj87cwJDgB0Lrs3pQIg== +"@open-wc/testing-helpers@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@open-wc/testing-helpers/-/testing-helpers-2.1.2.tgz#25ebc06074ea1d46633c3d1252dc5f7e1092244d" + integrity sha512-NEdsV47DnOWaw3Wpp85p4qZ6bdubtGPdlTiblk8vSf2HJ2sR4b3ckyRWzsj/k+pcxrDGt8z0Awz71p+048Rrfg== dependencies: "@open-wc/scoped-elements" "^2.0.1" lit "^2.0.0" lit-html "^2.0.0" "@open-wc/testing@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@open-wc/testing/-/testing-3.0.4.tgz#39148487919e00983b70e654926ae761ba577dfc" - integrity sha512-NR7POaSv6MCuJPjKq0O8jZXHL6dBugbPymQHcWGd67We9/G75upKYJYhIWETOOet/kNt3UrUKOGuTbsBx/RtAQ== + version "3.1.3" + resolved "https://registry.yarnpkg.com/@open-wc/testing/-/testing-3.1.3.tgz#df569a7654bf42ff156b4a498e93789d82b56fdb" + integrity sha512-7JXMVs02IqY/lhvBoc++MT9sVPQOVjFP9sapCtHz9PCDO3TGAVj1122eNyhhCiHsuG89wdk21GQILfAozfSeMA== dependencies: - "@esm-bundle/chai" "^4.3.4" + "@esm-bundle/chai" "^4.3.4-fix.0" "@open-wc/chai-dom-equals" "^0.12.36" "@open-wc/semantic-dom-diff" "^0.19.5" - "@open-wc/testing-helpers" "^2.0.4" + "@open-wc/testing-helpers" "^2.1.2" "@types/chai" "^4.2.11" "@types/chai-dom" "^0.0.9" "@types/sinon-chai" "^3.2.3" @@ -1806,9 +1805,21 @@ "@rollup/pluginutils" "^3.0.8" "@rollup/plugin-node-resolve@^11.0.1": - version "11.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.0.1.tgz#d3765eec4bccf960801439a999382aed2dca959b" - integrity sha512-ltlsj/4Bhwwhb+Nb5xCz/6vieuEj2/BAkkqVIKmZwC7pIdl8srmgmglE4S0jFlZa32K4qvdQ6NHdmpRKD/LwoQ== + version "11.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60" + integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + "@types/resolve" "1.17.1" + builtin-modules "^3.1.0" + deepmerge "^4.2.2" + is-module "^1.0.0" + resolve "^1.19.0" + +"@rollup/plugin-node-resolve@^13.0.4": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.2.1.tgz#cdee815cf02c180ff0a42536ca67a8f67e299f84" + integrity sha512-btX7kzGvp1JwShQI9V6IM841YKNPYjKCvUbNrQ2EcVYbULtUd/GH6wZ/qdqH13j9pOHBER+EZXNN2L8RSJhVRA== dependencies: "@rollup/pluginutils" "^3.1.0" "@types/resolve" "1.17.1" @@ -1842,6 +1853,14 @@ estree-walker "^1.0.1" picomatch "^2.2.2" +"@rollup/pluginutils@^4.1.0": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" + integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + "@sanity/block-content-to-hyperscript@^2.0.5": version "2.0.10" resolved "https://registry.yarnpkg.com/@sanity/block-content-to-hyperscript/-/block-content-to-hyperscript-2.0.10.tgz#9cf805c5d2341d043bcab8b3740c9b3466b5ae6b" @@ -2234,7 +2253,7 @@ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== -"@types/parse5@^5.0.0", "@types/parse5@^5.0.3": +"@types/parse5@^5.0.0": version "5.0.3" resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== @@ -2468,12 +2487,12 @@ picomatch "^2.2.2" ws "^7.4.2" -"@web/dev-server-rollup@^0.3.13": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@web/dev-server-rollup/-/dev-server-rollup-0.3.15.tgz#c0211fef837b9b733c1dd0849f60d4ece1c1dea4" - integrity sha512-hhxvBmNIY19vXeocYB1IBOuhpVpy1L7jbwBarmvC0QJKZsgkxssNTzXJ8iga70c2+H0c/rBz1xUaKuAcov0uOA== +"@web/dev-server-rollup@^0.3.16": + version "0.3.16" + resolved "https://registry.yarnpkg.com/@web/dev-server-rollup/-/dev-server-rollup-0.3.16.tgz#87f4a347cc8e6e28e41ff28cddaea5b3f965a395" + integrity sha512-JviPK0KFO2LjlK/Y1YMJtO9t+87uay7K+88BNC15VVrRV/j6PTk5D+ljDuSksSTQLD5XHKPd7QLbXINqyE5/lg== dependencies: - "@rollup/plugin-node-resolve" "^11.0.1" + "@rollup/plugin-node-resolve" "^13.0.4" "@web/dev-server-core" "^0.3.16" nanocolors "^0.2.1" parse5 "^6.0.1" @@ -2481,15 +2500,15 @@ whatwg-url "^11.0.0" "@web/dev-server@^0.1.24", "@web/dev-server@^0.1.4": - version "0.1.29" - resolved "https://registry.yarnpkg.com/@web/dev-server/-/dev-server-0.1.29.tgz#aaddf3d54b84f4d2a3af0e14f1de65d98ca6e8e3" - integrity sha512-oDz6vC9JEDZd4ZTno+SV57zCpsQl9v5LOkGuWGyei5gx5xu8NVDvh2IgTugz6DhZnffsSE6Zi0ubs+AhonLnGA== + version "0.1.31" + resolved "https://registry.yarnpkg.com/@web/dev-server/-/dev-server-0.1.31.tgz#b1cc316b64fcd061a8badf06281b7ea1fa26dba2" + integrity sha512-FGrnVwnL/pIxak1VZgOgnwcxvP90gx2LmXeU56nvZQ3CWNMAdS1rnQI3jMjMk6FwUt/wnlLk7pl6xGkm6iNwHA== dependencies: "@babel/code-frame" "^7.12.11" "@types/command-line-args" "^5.0.0" "@web/config-loader" "^0.1.3" "@web/dev-server-core" "^0.3.17" - "@web/dev-server-rollup" "^0.3.13" + "@web/dev-server-rollup" "^0.3.16" camelcase "^6.2.0" command-line-args "^5.1.1" command-line-usage "^6.1.1" @@ -2500,15 +2519,7 @@ open "^8.0.2" portfinder "^1.0.28" -"@web/parse5-utils@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@web/parse5-utils/-/parse5-utils-1.1.2.tgz#b53e7f62679170371da36023517b23bbb1f7c582" - integrity sha512-/JQHbK53BmYiFK2igr2B+Psl2Ivp2ju75Nx1InZweTbxLQNGG9yUBaudER85aqebIH6smkPkKwVtpdBXBiwy1A== - dependencies: - "@types/parse5" "^5.0.3" - parse5 "^6.0.1" - -"@web/parse5-utils@^1.2.0": +"@web/parse5-utils@^1.2.0", "@web/parse5-utils@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@web/parse5-utils/-/parse5-utils-1.3.0.tgz#e2e9e98b31a4ca948309f74891bda8d77399f6bd" integrity sha512-Pgkx3ECc8EgXSlS5EyrgzSOoUbM6P8OKS471HLAyvOBcP1NCBn0to4RN/OaKASGq8qa3j+lPX9H14uA5AHEnQg== @@ -2516,29 +2527,25 @@ "@types/parse5" "^6.0.1" parse5 "^6.0.1" -"@web/parse5-utils@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@web/parse5-utils/-/parse5-utils-1.2.2.tgz#33eec93321eb07cf364651c131b980a7afd8c4d7" - integrity sha512-B68DoJ5qF8Cu3o7nDA2RQTCf9bslVz2b0WHTk3qir5YCbWfhnPEGhDOedOjbE8xDiHqgzI1zXQsJ2+655aluLA== - dependencies: - "@types/parse5" "^5.0.3" - parse5 "^6.0.1" - -"@web/polyfills-loader@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@web/polyfills-loader/-/polyfills-loader-1.1.0.tgz#9df3da3d40159fce55c17cc370750052f62798bd" - integrity sha512-1bF1nhFG25isy6NbMhz9jVBCoXqrB1WzxkhT8Pyw9vKhXO+F83+TUWp0QeInsvvDVo0QPIeg+bVz6spRJrvfkg== +"@web/polyfills-loader@^1.3.4": + version "1.3.4" + resolved "https://registry.yarnpkg.com/@web/polyfills-loader/-/polyfills-loader-1.3.4.tgz#effbd6a7d8104ae3740641d015bef2ecb18e1ab6" + integrity sha512-MAXVz/0OSxsooGLiw7Wxi5gz95sPsLgeDI8lfHrlVlR4TogJigJY7cODZ6H6P9QydVQfN9uB2a4BfhT5+HwPdg== dependencies: "@babel/core" "^7.12.10" - "@web/parse5-utils" "^1.1.2" + "@web/parse5-utils" "^1.3.0" + "@webcomponents/shadycss" "^1.11.0" "@webcomponents/webcomponentsjs" "^2.5.0" abortcontroller-polyfill "^1.5.0" + construct-style-sheets-polyfill "^3.0.5" core-js-bundle "^3.8.1" dynamic-import-polyfill "^0.1.1" + es-module-shims "^1.4.1" intersection-observer "^0.12.0" parse5 "^6.0.1" regenerator-runtime "^0.13.7" resize-observer-polyfill "^1.5.1" + shady-css-scoped-element "^0.0.2" systemjs "^6.8.1" terser "^5.5.1" whatwg-fetch "^3.5.0" @@ -2551,30 +2558,30 @@ glob "^7.1.6" "@web/rollup-plugin-html@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@web/rollup-plugin-html/-/rollup-plugin-html-1.8.0.tgz#6be12acca2158f7aa105f1d6767ac8a95d5f02fc" - integrity sha512-aVOPpbnpXsIt0G3vVvtUz2ioKP9zUKmbE6wcTcFD/ncxM72JzTsUmIQAITGaoZMFjAwhKBEPYBbySDJJF/MvAg== + version "1.10.3" + resolved "https://registry.yarnpkg.com/@web/rollup-plugin-html/-/rollup-plugin-html-1.10.3.tgz#78fa06a9a7f2ec6973a12bd1000b900c1fd4e4eb" + integrity sha512-2RMIeKxpGtrcXiqPTgMVq5neGa5xa69MfNK860BHVMEO2N/MrHFuQNr1eNLsspcq2DL/xnymwC3w5hgjtlgxag== dependencies: - "@web/parse5-utils" "^1.2.2" + "@web/parse5-utils" "^1.3.0" glob "^7.1.6" - html-minifier-terser "^5.1.1" + html-minifier-terser "^6.0.0" parse5 "^6.0.1" "@web/rollup-plugin-import-meta-assets@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@web/rollup-plugin-import-meta-assets/-/rollup-plugin-import-meta-assets-1.0.4.tgz#32d7c381a976c8d40b9c3db861bc2f8651af849c" - integrity sha512-Yu1U63aMZdWY6SSRNlukuNBMB5TdDq530Bs2cFQOJ+bwWnz1OHE0JyvPRvDmG48jf1XMsIOaormbIruaRsP+KA== + version "1.0.7" + resolved "https://registry.yarnpkg.com/@web/rollup-plugin-import-meta-assets/-/rollup-plugin-import-meta-assets-1.0.7.tgz#7048f717e2218a22af547371ffafdc4f534a2eea" + integrity sha512-ft44CqITUkNd8stwNb4ZOvrZ8DlPifM821jplksmxRGetg5Lx684oFrpfQJ7mfkU/Sa7B3dI1mHTX0DE52eBwg== dependencies: - "@rollup/pluginutils" "^3.1.0" - estree-walker "^2.0.1" + "@rollup/pluginutils" "^4.1.0" + estree-walker "^2.0.2" magic-string "^0.25.7" "@web/rollup-plugin-polyfills-loader@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@web/rollup-plugin-polyfills-loader/-/rollup-plugin-polyfills-loader-1.1.0.tgz#5d49c11c6e9874550d8bac2934d368e6437c9982" - integrity sha512-p3GtEKeeyRJa5S/sKWpIa3eg+fiPeYux+Z+r85kxyAw4FY+4AOts9vEeg1McEDjCZ/4V40X2vaPTi1alFBNrig== + version "1.3.1" + resolved "https://registry.yarnpkg.com/@web/rollup-plugin-polyfills-loader/-/rollup-plugin-polyfills-loader-1.3.1.tgz#8cd22da8e7c661897285cae90e3b4bdf464dfdca" + integrity sha512-dV73QWsGMFkCGwgs2l6ADmDFtsEIduTJLSBL5wBHp5wZm1Sy4SQAEGTsDMRDX5cpAHRT9+sUnKLLREfBppuJbA== dependencies: - "@web/polyfills-loader" "^1.1.0" + "@web/polyfills-loader" "^1.3.4" "@web/test-runner-chrome@^0.10.7": version "0.10.7" @@ -2715,10 +2722,10 @@ portfinder "^1.0.28" source-map "^0.7.3" -"@webcomponents/scoped-custom-element-registry@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@webcomponents/scoped-custom-element-registry/-/scoped-custom-element-registry-0.0.3.tgz#774591a886b0b0e4914717273ba53fd8d5657522" - integrity sha512-lpSzgDCGbM99dytb3+J3Suo4+Bk1E13MPnWB42JK8GwxSAxFz+tC7TTv2hhDSIE2IirGNKNKCf3m08ecu6eAsQ== +"@webcomponents/shadycss@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@webcomponents/shadycss/-/shadycss-1.11.0.tgz#73e289996c002d8be694cd3be0e83c46ad25e7e0" + integrity sha512-L5O/+UPum8erOleNjKq6k58GVl3fNsEQdSOyh0EUhNmi7tHUyRuCJy1uqJiWydWcLARE5IPsMoPYMZmUGrz1JA== "@webcomponents/template-shadowroot@^0.1.0": version "0.1.0" @@ -2748,6 +2755,11 @@ acorn-jsx@^5.3.1: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== +acorn@^8.5.0: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + acorn@^8.6.0: version "8.6.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" @@ -3139,7 +3151,7 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@^4.1.1: +camel-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== @@ -3366,10 +3378,10 @@ class-list@~0.1.0, class-list@~0.1.1: dependencies: indexof "0.0.1" -clean-css@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" - integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== +clean-css@^5.2.2: + version "5.3.0" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.0.tgz#ad3d8238d5f3549e83d5f87205189494bc7cbb59" + integrity sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ== dependencies: source-map "~0.6.0" @@ -3516,7 +3528,7 @@ command-line-usage@^6.1.1: table-layout "^1.0.1" typical "^5.2.0" -commander@8.3.0: +commander@8.3.0, commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== @@ -3526,11 +3538,6 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - commander@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" @@ -3581,6 +3588,11 @@ concurrently@^5.3.0: tree-kill "^1.2.2" yargs "^13.3.0" +construct-style-sheets-polyfill@^3.0.5: + version "3.1.0" + resolved "https://registry.yarnpkg.com/construct-style-sheets-polyfill/-/construct-style-sheets-polyfill-3.1.0.tgz#c490abd79efdb359fafa62ec14ea55232be0eecf" + integrity sha512-HBLKP0chz8BAY6rBdzda11c3wAZeCZ+kIG4weVC2NM3AXzxx09nhe8t0SQNdloAvg5GLuHwq/0SPOOSPvtCcKw== + content-disposition@~0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -4086,6 +4098,11 @@ es-module-lexer@^0.9.0, es-module-lexer@^0.9.3: resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-shims@^1.4.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-shims/-/es-module-shims-1.5.4.tgz#952662871bed8ac996b7213f6943830c02b9fa9e" + integrity sha512-OoVOu69uuLCnlMIcZJnYjZmp/0qhnisTUinU2WtIHztM65S1+SozyiDrmJgowScuMdYO41g8FmII+YXrkZwypA== + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -4255,7 +4272,7 @@ estree-walker@^1.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== -estree-walker@^2.0.1: +estree-walker@^2.0.1, estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== @@ -5004,18 +5021,18 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -html-minifier-terser@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" - integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== +html-minifier-terser@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== dependencies: - camel-case "^4.1.1" - clean-css "^4.2.3" - commander "^4.1.1" + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" he "^1.2.0" - param-case "^3.0.3" + param-case "^3.0.4" relateurl "^0.2.7" - terser "^4.6.3" + terser "^5.10.0" html-void-elements@^1.0.0: version "1.0.5" @@ -7045,7 +7062,7 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -param-case@^3.0.3: +param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== @@ -8153,6 +8170,11 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== +shady-css-scoped-element@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/shady-css-scoped-element/-/shady-css-scoped-element-0.0.2.tgz#c538fcfe2317e979cd02dfec533898b95b4ea8fe" + integrity sha512-Dqfl70x6JiwYDujd33ZTbtCK0t52E7+H2swdWQNSTzfsolSa6LJHnTpN4T9OpJJEq4bxuzHRLFO9RBcy/UfrMQ== + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -8192,10 +8214,10 @@ simple-concat@^1.0.1: resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== -singleton-manager@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/singleton-manager/-/singleton-manager-1.4.2.tgz#4649acafca3eccf987d828ab16369ee59c4a22a5" - integrity sha512-3/K7K61TiN0+tw32HRC3AZQBacN0Ky/NmHEnhofFPEFROqZ5T6BXK45Z94OQsvuFD2euOVOU40XDNeTal63Baw== +singleton-manager@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/singleton-manager/-/singleton-manager-1.4.3.tgz#bdfd71e3b8c99ee8a0d9086496a795c84f886d0e" + integrity sha512-Jy1Ib9cO9xCQ6UZ/vyFOqqWMnSpfZ8/Sc2vme944aWsCLO+lMPiFG9kGZGpyiRT9maYeI0JyZH1CGgjmkSN8VA== sinon@^9.2.3: version "9.2.3" @@ -8277,7 +8299,7 @@ source-map-support@^0.4.18: dependencies: source-map "^0.5.6" -source-map-support@^0.5.17, source-map-support@~0.5.12, source-map-support@~0.5.19: +source-map-support@^0.5.17: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -8285,12 +8307,20 @@ source-map-support@^0.5.17, source-map-support@~0.5.12, source-map-support@~0.5. buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@~0.6.0, source-map@~0.6.1: +source-map@^0.6.0, source-map@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -8612,32 +8642,15 @@ term-size@^2.1.0: resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== -terser@^4.6.3: - version "4.8.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" - integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -terser@^5.0.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.5.1.tgz#540caa25139d6f496fdea056e414284886fb2289" - integrity sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ== - dependencies: - commander "^2.20.0" - source-map "~0.7.2" - source-map-support "~0.5.19" - -terser@^5.5.1: - version "5.6.1" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.6.1.tgz#a48eeac5300c0a09b36854bf90d9c26fb201973c" - integrity sha512-yv9YLFQQ+3ZqgWCUk+pvNJwgUTdlIxUk1WTN+RnaFJe2L7ipG2csPT0ra2XRm7Cs8cxN7QXmK1rFzEwYEQkzXw== +terser@^5.0.0, terser@^5.10.0, terser@^5.5.1: + version "5.12.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.12.1.tgz#4cf2ebed1f5bceef5c83b9f60104ac4a78b49e9c" + integrity sha512-NXbs+7nisos5E+yXwAD+y7zrcTkMqb0dEJxIGtSKPdCBzopf7ni4odPul2aechpV7EXNvOudYOX2bb5tln1jbQ== dependencies: + acorn "^8.5.0" commander "^2.20.0" source-map "~0.7.2" - source-map-support "~0.5.19" + source-map-support "~0.5.20" text-table@^0.2.0: version "0.2.0" @@ -8834,10 +8847,10 @@ typescript@^4.6.0-dev.20211126: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.0-dev.20211126.tgz#d27ce3a360dc4da1dcdebd80efe42b51afdeebdb" integrity sha512-m+LKstqVv6FYW363aIbO6bm8awsLbeSUCzU6FxPtzUF/WJkFieQfYmdVwEIzigeTpw4E2GETBXnk6P6AixcQJQ== -typescript@^4.6.1-rc: - version "4.6.1-rc" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.1-rc.tgz#75baa823a6fca592f358b486acc2039f103ca2af" - integrity sha512-tLPT3GelVfTN9wXPOuPKfY83PkMvgdF3V3gHK/ElNrpQPdLKQ/HMU5cS6+7epYSIF2gne190jzydAW0FLLwU7A== +typescript@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c" + integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw== typical@^4.0.0: version "4.0.0"