@janga/norna 0.7.10 → 0.7.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -106
- package/bin/norna-cli.mjs +4 -1
- package/docs/README.md +107 -74
- package/docs/assets/norna-dog-shelter.jpg +0 -0
- package/docs/commands.md +13 -4
- package/docs/configuration.md +86 -184
- package/docs/content.md +14 -14
- package/docs/design/command-organization.md +1 -1
- package/docs/design/norna-diagram-design.md +2 -1
- package/docs/design/site-examples-structure.md +38 -24
- package/docs/engine-development.md +28 -15
- package/docs/getting-started.md +141 -124
- package/docs/how-to/embedded-site.md +35 -0
- package/docs/publishing.md +47 -46
- package/docs/requirements.md +54 -0
- package/docs/routes.md +3 -2
- package/docs/site-structure.md +12 -9
- package/docs/sitewide-content.md +2 -1
- package/docs/theme.md +104 -34
- package/docs/typography.md +32 -17
- package/examples/README.md +43 -0
- package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/.astro/collections/sitewide.schema.json +24 -0
- package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/.astro/collections/theme.schema.json +9 -24
- package/examples/{dog-gallery → complete-sites/dog-shelter-multi-page}/.astro/content.d.ts +9 -1
- package/examples/complete-sites/dog-shelter-multi-page/.astro/data-store.json +1 -0
- package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/.astro/dev-local.json +2 -2
- package/examples/complete-sites/dog-shelter-multi-page/.astro/dev.json +13 -0
- package/examples/complete-sites/dog-shelter-multi-page/.astro/dev.log +26 -0
- package/examples/complete-sites/dog-shelter-multi-page/.astro/settings.json +5 -0
- package/examples/complete-sites/dog-shelter-multi-page/README.md +16 -0
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/_metadata.json +74 -0
- package/examples/{typography-presets/node_modules/.vite/deps/astro-D_GIpJIE.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro-B3JHJyiv.js} +4 -4
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro-B3JHJyiv.js.map +1 -0
- package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/node_modules/.vite/deps/astro_n_aria-query.js +151 -151
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/node_modules/.vite/deps/astro_n_axobject-query.js +131 -131
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/node_modules/.vite/deps/astro_n_html-escaper.js +1 -1
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +10 -10
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/audit-DM9Hkl5B.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/audit-C3SVr7dT.js} +10 -10
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/audit-C3SVr7dT.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/highlight-DnZ1ULOL.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/highlight-BLtvqtzO.js} +1 -1
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/icons-RyebKi45.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/icons-C92i61-2.js} +1 -1
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/icons-C92i61-2.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/settings-DaU-gNnK.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/settings-v5GgKks_.js} +2 -2
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/settings-v5GgKks_.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/toolbar-63PA619H.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/toolbar-BFvJVp26.js} +2 -2
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/ui-library--bkcNSYz.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js} +10 -10
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/window-jPkpKVcy.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/window-vo3A6TMn.js} +1 -1
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/window-vo3A6TMn.js.map +1 -0
- package/examples/{typography-presets/node_modules/.vite/deps/xray-BXCHpEJP.js → complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/xray-DwhzGckb.js} +3 -3
- package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/xray-DwhzGckb.js.map +1 -0
- package/examples/complete-sites/dog-shelter-multi-page/site/.norna/generated-images.json +98 -0
- package/examples/complete-sites/dog-shelter-multi-page/site/config.md +3 -0
- package/examples/{002-dog-shelter-multi-page → complete-sites/dog-shelter-multi-page}/site/content.md +12 -0
- package/examples/complete-sites/dog-shelter-multi-page/site/public/logo.svg +9 -0
- package/examples/complete-sites/dog-shelter-multi-page/site/routes/010-dogs/route-content.md +22 -0
- package/examples/{002-dog-shelter-multi-page → complete-sites/dog-shelter-multi-page}/site/routes/020-adopt/route-content.md +11 -0
- package/examples/complete-sites/dog-shelter-multi-page/site/sitewide-content.md +16 -0
- package/examples/complete-sites/dog-shelter-multi-page/site/theme.md +3 -0
- package/examples/complete-sites/dog-shelter-single-page/.astro/collections/site.schema.json +59 -0
- package/examples/complete-sites/dog-shelter-single-page/.astro/collections/sitewide.schema.json +138 -0
- package/examples/{dog-gallery → complete-sites/dog-shelter-single-page}/.astro/collections/theme.schema.json +151 -68
- package/examples/complete-sites/dog-shelter-single-page/.astro/content.d.ts +183 -0
- package/examples/complete-sites/dog-shelter-single-page/.astro/data-store.json +1 -0
- package/examples/complete-sites/dog-shelter-single-page/.astro/dev.json +13 -0
- package/examples/complete-sites/dog-shelter-single-page/.astro/dev.log +14 -0
- package/examples/complete-sites/dog-shelter-single-page/.astro/settings.json +5 -0
- package/examples/complete-sites/dog-shelter-single-page/README.md +16 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/_metadata.json +74 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro-B3JHJyiv.js +434 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro-B3JHJyiv.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_axobject-query.js +2702 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/audit-C3SVr7dT.js +1534 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/audit-C3SVr7dT.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/highlight-BLtvqtzO.js +48 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/icons-C92i61-2.js +42 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/icons-C92i61-2.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/settings-v5GgKks_.js +190 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/settings-v5GgKks_.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/toolbar-BFvJVp26.js +458 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js +1016 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/window-vo3A6TMn.js +32 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/window-vo3A6TMn.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/xray-DwhzGckb.js +111 -0
- package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/xray-DwhzGckb.js.map +1 -0
- package/examples/complete-sites/dog-shelter-single-page/site/.norna/generated-images.json +50 -0
- package/examples/complete-sites/dog-shelter-single-page/site/config.md +3 -0
- package/examples/complete-sites/dog-shelter-single-page/site/content.md +34 -0
- package/examples/complete-sites/dog-shelter-single-page/site/public/logo.svg +9 -0
- package/examples/complete-sites/dog-shelter-single-page/site/sitewide-content.md +16 -0
- package/examples/complete-sites/dog-shelter-single-page/site/theme.md +3 -0
- package/examples/feature-demos/media-and-surfaces/.astro/collections/site.schema.json +59 -0
- package/examples/feature-demos/media-and-surfaces/.astro/collections/sitewide.schema.json +138 -0
- package/examples/feature-demos/media-and-surfaces/.astro/collections/theme.schema.json +755 -0
- package/examples/feature-demos/media-and-surfaces/.astro/content-assets.mjs +4 -0
- package/examples/feature-demos/media-and-surfaces/.astro/content-modules.mjs +1 -0
- package/examples/feature-demos/media-and-surfaces/.astro/content.d.ts +183 -0
- package/examples/feature-demos/media-and-surfaces/.astro/data-store.json +1 -0
- package/examples/feature-demos/media-and-surfaces/.astro/dev.log +24 -0
- package/examples/feature-demos/media-and-surfaces/.astro/settings.json +5 -0
- package/examples/feature-demos/media-and-surfaces/.astro/types.d.ts +2 -0
- package/examples/feature-demos/media-and-surfaces/README.md +21 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/_metadata.json +80 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro-B3JHJyiv.js +434 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro-B3JHJyiv.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_axobject-query.js +2702 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/audit-C3SVr7dT.js +1534 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/audit-C3SVr7dT.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/embla-carousel.js +1389 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/embla-carousel.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/highlight-BLtvqtzO.js +48 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/icons-C92i61-2.js +42 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/icons-C92i61-2.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/package.json +3 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +4 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/settings-v5GgKks_.js +190 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/settings-v5GgKks_.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/toolbar-BFvJVp26.js +458 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/ui-library-Cd35oAvo.js +1016 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/window-vo3A6TMn.js +32 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/window-vo3A6TMn.js.map +1 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/xray-DwhzGckb.js +111 -0
- package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/xray-DwhzGckb.js.map +1 -0
- package/examples/{presentation → feature-demos/media-and-surfaces}/site/.norna/generated-images.json +16 -16
- package/examples/feature-demos/media-and-surfaces/site/config.md +4 -0
- package/examples/feature-demos/media-and-surfaces/site/content.md +18 -0
- package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/route-content.md +17 -24
- package/examples/{presentation/site/routes/030-surfaces → feature-demos/media-and-surfaces/site/routes/020-surfaces}/route-content.md +1 -1
- package/examples/{presentation/site/routes/030-surfaces → feature-demos/media-and-surfaces/site/routes/020-surfaces}/theme.md +1 -0
- package/examples/feature-demos/media-and-surfaces/site/sitewide-content.md +6 -0
- package/examples/feature-demos/media-and-surfaces/site/theme.md +3 -0
- package/examples/feature-demos/sitewide-content/.astro/collections/site.schema.json +59 -0
- package/examples/feature-demos/sitewide-content/.astro/collections/sitewide.schema.json +138 -0
- package/examples/feature-demos/sitewide-content/.astro/collections/theme.schema.json +755 -0
- package/examples/feature-demos/sitewide-content/.astro/content-assets.mjs +1 -0
- package/examples/feature-demos/sitewide-content/.astro/content-modules.mjs +1 -0
- package/examples/feature-demos/sitewide-content/.astro/content.d.ts +183 -0
- package/examples/feature-demos/sitewide-content/.astro/data-store.json +1 -0
- package/examples/feature-demos/sitewide-content/.astro/dev.json +13 -0
- package/examples/feature-demos/sitewide-content/.astro/dev.log +18 -0
- package/examples/feature-demos/sitewide-content/.astro/settings.json +5 -0
- package/examples/feature-demos/sitewide-content/.astro/types.d.ts +2 -0
- package/examples/feature-demos/sitewide-content/README.md +18 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/_metadata.json +74 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro-B3JHJyiv.js +434 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro-B3JHJyiv.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_axobject-query.js +2702 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/audit-C3SVr7dT.js +1534 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/audit-C3SVr7dT.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/highlight-BLtvqtzO.js +48 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/icons-C92i61-2.js +42 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/icons-C92i61-2.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/package.json +3 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +4 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/settings-v5GgKks_.js +190 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/settings-v5GgKks_.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/toolbar-BFvJVp26.js +458 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/ui-library-Cd35oAvo.js +1016 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/window-vo3A6TMn.js +32 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/window-vo3A6TMn.js.map +1 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/xray-DwhzGckb.js +111 -0
- package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/xray-DwhzGckb.js.map +1 -0
- package/examples/feature-demos/sitewide-content/site/.norna/generated-images.json +1 -0
- package/examples/feature-demos/sitewide-content/site/config.md +3 -0
- package/examples/feature-demos/sitewide-content/site/content.md +16 -0
- package/examples/feature-demos/sitewide-content/site/public/logo.svg +6 -0
- package/examples/feature-demos/sitewide-content/site/routes/010-identity/route-content.md +20 -0
- package/examples/feature-demos/sitewide-content/site/routes/020-notices/route-content.md +22 -0
- package/examples/feature-demos/sitewide-content/site/routes/030-footer/route-content.md +17 -0
- package/examples/feature-demos/sitewide-content/site/sitewide-content.md +33 -0
- package/examples/feature-demos/sitewide-content/site/theme.md +3 -0
- package/examples/feature-demos/theme-presets/.astro/collections/site.schema.json +59 -0
- package/examples/feature-demos/theme-presets/.astro/collections/sitewide.schema.json +138 -0
- package/examples/feature-demos/theme-presets/.astro/collections/theme.schema.json +755 -0
- package/examples/feature-demos/theme-presets/.astro/content-assets.mjs +4 -0
- package/examples/feature-demos/theme-presets/.astro/content-modules.mjs +1 -0
- package/examples/{typography-presets → feature-demos/theme-presets}/.astro/data-store.json +1 -1
- package/examples/feature-demos/theme-presets/.astro/dev-local.json +8 -0
- package/examples/{typography-presets → feature-demos/theme-presets}/.astro/dev.json +2 -2
- package/examples/feature-demos/theme-presets/.astro/dev.log +164 -0
- package/examples/feature-demos/theme-presets/.astro/types.d.ts +2 -0
- package/examples/feature-demos/theme-presets/README.md +18 -0
- package/examples/feature-demos/theme-presets/node_modules/.vite/deps/package.json +3 -0
- package/examples/feature-demos/theme-presets/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +4 -0
- package/examples/{typography-presets → feature-demos/theme-presets}/site/.norna/generated-images.json +45 -45
- package/examples/feature-demos/theme-presets/site/config.md +3 -0
- package/examples/feature-demos/theme-presets/site/content.md +17 -0
- package/examples/feature-demos/theme-presets/site/routes/010-portfolio/images/portfolio/shepherd-portrait.jpg +0 -0
- package/examples/feature-demos/theme-presets/site/routes/010-portfolio/images/portfolio/white-puppy.jpg +0 -0
- package/examples/{typography-presets/site/routes/010-quiet-gallery → feature-demos/theme-presets/site/routes/010-portfolio}/route-content.md +8 -8
- package/examples/feature-demos/theme-presets/site/routes/010-portfolio/theme.md +3 -0
- package/examples/feature-demos/theme-presets/site/routes/020-documentation/images/documentation/retriever-portrait.jpg +0 -0
- package/examples/{typography-presets/site/routes/020-compact-gallery → feature-demos/theme-presets/site/routes/020-documentation}/route-content.md +8 -8
- package/examples/feature-demos/theme-presets/site/routes/020-documentation/theme.md +3 -0
- package/examples/feature-demos/theme-presets/site/routes/030-project/images/project/boxer-portrait.jpg +0 -0
- package/examples/feature-demos/theme-presets/site/routes/030-project/images/project/grass-puppy.jpg +0 -0
- package/examples/{typography-presets/site/routes/030-text-forward → feature-demos/theme-presets/site/routes/030-project}/route-content.md +8 -8
- package/examples/feature-demos/theme-presets/site/routes/030-project/theme.md +3 -0
- package/examples/feature-demos/theme-presets/site/routes/040-statement/images/statement/sheepdog-grass.jpg +0 -0
- package/examples/{typography-presets → feature-demos/theme-presets}/site/routes/040-statement/route-content.md +3 -3
- package/examples/feature-demos/theme-presets/site/routes/040-statement/theme.md +3 -0
- package/examples/{typography-presets → feature-demos/theme-presets}/site/sitewide-content.md +1 -1
- package/examples/feature-demos/theme-presets/site/theme.md +3 -0
- package/fixtures/basic/site/config.md +3 -0
- package/fixtures/content-model-v2/site/config.md +3 -0
- package/package.json +17 -8
- package/scripts/build-pages.mjs +69 -0
- package/scripts/check-config.mjs +3 -11
- package/scripts/deploy-site.mjs +12 -8
- package/scripts/export-theme-preset.mjs +31 -0
- package/scripts/init-site.mjs +1 -0
- package/scripts/lib/example-sites.mjs +37 -0
- package/scripts/lib/github-repository.mjs +44 -0
- package/scripts/lib/norna-markdown-blocks.mjs +97 -10
- package/scripts/lib/presentation.mjs +6 -5
- package/scripts/lib/project-config.mjs +114 -124
- package/scripts/lib/site-content.mjs +9 -2
- package/scripts/lib/site-paths.mjs +6 -2
- package/scripts/lib/theme-config.mjs +3 -0
- package/scripts/lib/theme-presets.mjs +209 -0
- package/scripts/show-typography.mjs +6 -5
- package/scripts/test-client-javascript.mjs +236 -0
- package/scripts/test-content-check.mjs +103 -0
- package/scripts/test-content-model-v2.mjs +9 -13
- package/scripts/test-documentation.mjs +116 -0
- package/scripts/test-engine-commands.mjs +13 -3
- package/scripts/test-examples.mjs +24 -0
- package/scripts/test-navigation.mjs +73 -45
- package/scripts/test-package-check.mjs +17 -9
- package/scripts/test-project-config.mjs +130 -0
- package/scripts/test-temporary-visibility.mjs +3 -10
- package/scripts/test-theme-presets.mjs +146 -0
- package/scripts/watch-pages-deploy.mjs +15 -11
- package/src/components/GalleryGrid.astro +30 -230
- package/src/components/ImageCarousel.astro +184 -0
- package/src/components/MobileSectionNavigationScript.astro +14 -0
- package/src/components/NornaSmoothScrollScript.astro +250 -0
- package/src/components/SiteNavigation.astro +58 -341
- package/src/components/SiteNotesScript.astro +43 -0
- package/src/components/SitePage.astro +6 -3
- package/src/components/SiteSection.astro +4 -47
- package/src/content.config.ts +2 -0
- package/src/layouts/BaseLayout.astro +1 -1
- package/src/lib/galleryImages.ts +53 -0
- package/src/styles/global.css +83 -1
- package/starters/basic/.github/workflows/deploy.yml +1 -2
- package/starters/basic/README.md +10 -8
- package/starters/basic/package.json +1 -0
- package/starters/basic/site/config.md +3 -0
- package/starters/project/.github/workflows/deploy.yml +1 -2
- package/starters/project/README.md +3 -4
- package/starters/project/package.json +1 -0
- package/starters/project/site/config.md +3 -0
- package/examples/001-dog-shelter-single-page/README.md +0 -9
- package/examples/001-dog-shelter-single-page/site/config.mjs +0 -27
- package/examples/001-dog-shelter-single-page/site/content.md +0 -38
- package/examples/001-dog-shelter-single-page/site/images/what-we-do/dog-house.svg +0 -25
- package/examples/001-dog-shelter-single-page/site/images/you-can-help/heart.svg +0 -13
- package/examples/001-dog-shelter-single-page/site/sitewide-content.md +0 -6
- package/examples/001-dog-shelter-single-page/site/theme.md +0 -25
- package/examples/002-dog-shelter-multi-page/README.md +0 -9
- package/examples/002-dog-shelter-multi-page/site/config.mjs +0 -27
- package/examples/002-dog-shelter-multi-page/site/routes/010-dogs/images/dogs/rex.svg +0 -19
- package/examples/002-dog-shelter-multi-page/site/routes/010-dogs/images/dogs/rover.svg +0 -19
- package/examples/002-dog-shelter-multi-page/site/routes/010-dogs/route-content.md +0 -30
- package/examples/002-dog-shelter-multi-page/site/sitewide-content.md +0 -6
- package/examples/002-dog-shelter-multi-page/site/theme.md +0 -25
- package/examples/dog-gallery/.astro/collections/site.schema.json +0 -776
- package/examples/dog-gallery/.astro/data-store.json +0 -1
- package/examples/dog-gallery/.astro/dev-local.json +0 -8
- package/examples/dog-gallery/.astro/dev.json +0 -13
- package/examples/dog-gallery/.astro/dev.log +0 -95
- package/examples/dog-gallery/.astro/settings.json +0 -5
- package/examples/dog-gallery/dist/_astro/GalleryGrid.astro_astro_type_script_index_0_lang.B0kxDyGz.js +0 -1
- package/examples/dog-gallery/dist/_astro/SitePage.DicGh_5N.css +0 -1
- package/examples/dog-gallery/dist/dog-care/index.html +0 -15
- package/examples/dog-gallery/dist/dog-shelter-logo.svg +0 -14
- package/examples/dog-gallery/dist/favicon.svg +0 -7
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1536.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-960.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-3939.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-2400.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1600.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-2576.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-1277.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1536.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-768.webp +0 -0
- package/examples/dog-gallery/dist/index.html +0 -45
- package/examples/dog-gallery/node_modules/.vite/deps/_metadata.json +0 -74
- package/examples/dog-gallery/site/.norna/generated-images.json +0 -226
- package/examples/dog-gallery/site/config.mjs +0 -47
- package/examples/dog-gallery/site/content.md +0 -127
- package/examples/dog-gallery/site/images/black-dogs/black-puppy-meadow.png +0 -0
- package/examples/dog-gallery/site/images/black-dogs/photo-of-a-black-dog.jpg +0 -0
- package/examples/dog-gallery/site/images/brown-dogs/brown-dog.jpg +0 -0
- package/examples/dog-gallery/site/images/brown-dogs/dog-accompanies-master.jpg +0 -0
- package/examples/dog-gallery/site/images/golden-dogs/golden-retriever.jpg +0 -0
- package/examples/dog-gallery/site/images/golden-dogs/toller-puppy.jpg +0 -0
- package/examples/dog-gallery/site/images/white-dogs/white-cute-dog.jpg +0 -0
- package/examples/dog-gallery/site/images/white-dogs/white-puppy-garden.png +0 -0
- package/examples/dog-gallery/site/public/favicon.svg +0 -7
- package/examples/dog-gallery/site/public/logo.svg +0 -14
- package/examples/dog-gallery/site/routes/010-dog-care/route-content.md +0 -38
- package/examples/dog-gallery/site/sitewide-content.md +0 -16
- package/examples/dog-gallery/site/theme.md +0 -101
- package/examples/presentation/README.md +0 -15
- package/examples/presentation/site/config.mjs +0 -29
- package/examples/presentation/site/content.md +0 -67
- package/examples/presentation/site/public/robots.txt +0 -2
- package/examples/presentation/site/routes/010-presets/route-content.md +0 -63
- package/examples/presentation/site/routes/010-presets/theme.md +0 -4
- package/examples/presentation/site/routes/020-media/theme.md +0 -4
- package/examples/presentation/site/sitewide-content.md +0 -6
- package/examples/presentation/site/theme.md +0 -43
- package/examples/typography-presets/.astro/dev.log +0 -45
- package/examples/typography-presets/node_modules/.vite/deps/astro-D_GIpJIE.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/icons-RyebKi45.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/settings-DaU-gNnK.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/toolbar-63PA619H.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/window-jPkpKVcy.js.map +0 -1
- package/examples/typography-presets/node_modules/.vite/deps/xray-BXCHpEJP.js.map +0 -1
- package/examples/typography-presets/site/config.mjs +0 -29
- package/examples/typography-presets/site/content.md +0 -16
- package/examples/typography-presets/site/routes/010-quiet-gallery/theme.md +0 -4
- package/examples/typography-presets/site/routes/020-compact-gallery/theme.md +0 -4
- package/examples/typography-presets/site/routes/030-text-forward/theme.md +0 -4
- package/examples/typography-presets/site/routes/040-statement/theme.md +0 -4
- package/examples/typography-presets/site/theme.md +0 -43
- package/fixtures/basic/site/config.mjs +0 -27
- package/fixtures/content-model-v2/site/config.mjs +0 -11
- package/starters/basic/site/config.mjs +0 -27
- package/starters/project/site/config.mjs +0 -30
- /package/examples/{typography-presets → complete-sites/dog-shelter-multi-page}/.astro/collections/site.schema.json +0 -0
- /package/examples/{dog-gallery → complete-sites/dog-shelter-multi-page}/.astro/content-assets.mjs +0 -0
- /package/examples/{dog-gallery → complete-sites/dog-shelter-multi-page}/.astro/content-modules.mjs +0 -0
- /package/examples/{dog-gallery → complete-sites/dog-shelter-multi-page}/.astro/types.d.ts +0 -0
- /package/examples/{dog-gallery → complete-sites/dog-shelter-multi-page}/node_modules/.vite/deps/package.json +0 -0
- /package/examples/{dog-gallery → complete-sites/dog-shelter-multi-page}/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -0
- /package/examples/{typography-presets/site/routes/020-compact-gallery/images/compact-gallery/retriever-portrait.jpg → complete-sites/dog-shelter-multi-page/site/images/intro/shelter-dog.jpg} +0 -0
- /package/examples/{001-dog-shelter-single-page → complete-sites/dog-shelter-multi-page}/site/public/favicon.svg +0 -0
- /package/examples/{001-dog-shelter-single-page → complete-sites/dog-shelter-multi-page}/site/public/robots.txt +0 -0
- /package/examples/{typography-presets/site/routes/010-quiet-gallery/images/quiet-gallery/white-puppy.jpg → complete-sites/dog-shelter-multi-page/site/routes/010-dogs/images/dogs/rex.jpg} +0 -0
- /package/examples/{typography-presets/site/routes/030-text-forward/images/text-forward/boxer-portrait.jpg → complete-sites/dog-shelter-multi-page/site/routes/010-dogs/images/dogs/rover.jpg} +0 -0
- /package/examples/{typography-presets/site/routes/040-statement/images/statement/sheepdog-grass.jpg → complete-sites/dog-shelter-multi-page/site/routes/020-adopt/images/adopt/adoption-dog.jpg} +0 -0
- /package/examples/{typography-presets → complete-sites/dog-shelter-single-page}/.astro/content-assets.mjs +0 -0
- /package/examples/{typography-presets → complete-sites/dog-shelter-single-page}/.astro/content-modules.mjs +0 -0
- /package/examples/{typography-presets → complete-sites/dog-shelter-single-page}/.astro/types.d.ts +0 -0
- /package/examples/{typography-presets → complete-sites/dog-shelter-single-page}/node_modules/.vite/deps/package.json +0 -0
- /package/examples/{typography-presets → complete-sites/dog-shelter-single-page}/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -0
- /package/examples/{typography-presets/site/routes/030-text-forward/images/text-forward/grass-puppy.jpg → complete-sites/dog-shelter-single-page/site/images/what-we-do/rescue-dog.jpg} +0 -0
- /package/examples/{typography-presets/site/routes/010-quiet-gallery/images/quiet-gallery/shepherd-portrait.jpg → complete-sites/dog-shelter-single-page/site/images/you-can-help/foster-dog.jpg} +0 -0
- /package/examples/{002-dog-shelter-multi-page → complete-sites/dog-shelter-single-page}/site/public/favicon.svg +0 -0
- /package/examples/{002-dog-shelter-multi-page → complete-sites/dog-shelter-single-page}/site/public/robots.txt +0 -0
- /package/examples/{dog-gallery/dist → feature-demos/media-and-surfaces/site/public}/robots.txt +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/cards/card-carousel.svg +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/cards/card-stack.svg +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/cards/card-surfaces.svg +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/carousel/carousel-one.svg +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/carousel/carousel-three.svg +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/carousel/carousel-two.svg +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/stack/stack-one.svg +0 -0
- /package/examples/{presentation/site/routes/020-media → feature-demos/media-and-surfaces/site/routes/010-media}/images/stack/stack-two.svg +0 -0
- /package/examples/{dog-gallery → feature-demos/sitewide-content}/site/public/robots.txt +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/.astro/collections/routeTheme.schema.json +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/.astro/content.d.ts +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/.astro/settings.json +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/node_modules/.vite/deps/_metadata.json +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro-D_GIpJIE.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro-D_GIpJIE.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_n_aria-query.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_n_axobject-query.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_n_html-escaper.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/audit-DM9Hkl5B.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/node_modules/.vite/deps/embla-carousel.js +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/node_modules/.vite/deps/embla-carousel.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/highlight-DnZ1ULOL.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/icons-RyebKi45.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/icons-RyebKi45.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/settings-DaU-gNnK.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/settings-DaU-gNnK.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/toolbar-63PA619H.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/toolbar-63PA619H.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/ui-library--bkcNSYz.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/window-jPkpKVcy.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/window-jPkpKVcy.js.map +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/xray-BXCHpEJP.js +0 -0
- /package/examples/{dog-gallery → feature-demos/theme-presets}/node_modules/.vite/deps/xray-BXCHpEJP.js.map +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/site/public/robots.txt +0 -0
- /package/examples/{typography-presets/site/routes/010-quiet-gallery/images/quiet-gallery → feature-demos/theme-presets/site/routes/010-portfolio/images/portfolio}/puppy-portrait.jpg +0 -0
- /package/examples/{typography-presets/site/routes/020-compact-gallery/images/compact-gallery → feature-demos/theme-presets/site/routes/020-documentation/images/documentation}/black-schnauzer.jpg +0 -0
- /package/examples/{typography-presets/site/routes/020-compact-gallery/images/compact-gallery → feature-demos/theme-presets/site/routes/020-documentation/images/documentation}/schnauzer-portrait.jpg +0 -0
- /package/examples/{typography-presets/site/routes/030-text-forward/images/text-forward → feature-demos/theme-presets/site/routes/030-project/images/project}/grey-street-dog.jpg +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/site/routes/040-statement/images/statement/black-pedigree.jpg +0 -0
- /package/examples/{typography-presets → feature-demos/theme-presets}/site/routes/040-statement/images/statement/sheepdog-wide.jpg +0 -0
|
@@ -51,17 +51,9 @@ const createTempSite = async ({ underRepoCache = false } = {}) => {
|
|
|
51
51
|
const root = await mkdtemp(path.join(tempParent, 'norna-content-model-v2-'));
|
|
52
52
|
const siteDir = path.join(root, 'site');
|
|
53
53
|
await mkdir(siteDir, { recursive: true });
|
|
54
|
-
await writeFile(path.join(siteDir, 'config.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
basePath: '/',
|
|
58
|
-
},
|
|
59
|
-
github: {
|
|
60
|
-
branch: 'main',
|
|
61
|
-
repo: 'owner/repo',
|
|
62
|
-
pagesWorkflow: 'Deploy to GitHub Pages',
|
|
63
|
-
},
|
|
64
|
-
};
|
|
54
|
+
await writeFile(path.join(siteDir, 'config.md'), `---
|
|
55
|
+
url: https://example.com/
|
|
56
|
+
---
|
|
65
57
|
`);
|
|
66
58
|
await writeFile(path.join(siteDir, 'theme.md'), `---
|
|
67
59
|
typography:
|
|
@@ -294,11 +286,15 @@ description: Fixture
|
|
|
294
286
|
|
|
295
287
|
The first paragraph points to an explanation.{note-ref}
|
|
296
288
|
|
|
297
|
-
{note: This explanation names \`sitewide-content.md\` and stays beside the
|
|
289
|
+
{note: This explanation names \`sitewide-content.md\` and stays beside the
|
|
290
|
+
paragraph on wide screens.}
|
|
298
291
|
|
|
299
292
|
The second paragraph has its own explanation.{note-ref}
|
|
300
293
|
|
|
301
|
-
{note:
|
|
294
|
+
{note:
|
|
295
|
+
This is the second
|
|
296
|
+
explanation.
|
|
297
|
+
}
|
|
302
298
|
`);
|
|
303
299
|
|
|
304
300
|
await runNorna(['--site-dir', siteDir, 'build']);
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { mkdir, mkdtemp, readFile, readdir, rm, symlink, writeFile } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
|
|
7
|
+
const repoRoot = path.resolve(import.meta.dirname, '..');
|
|
8
|
+
const cliPath = path.join(repoRoot, 'bin', 'norna.mjs');
|
|
9
|
+
const tutorialPath = path.join(repoRoot, 'docs', 'getting-started.md');
|
|
10
|
+
const scratchRoot = path.join(repoRoot, 'todos');
|
|
11
|
+
await mkdir(scratchRoot, { recursive: true });
|
|
12
|
+
const tempRoot = await mkdtemp(path.join(scratchRoot, 'norna-documentation-'));
|
|
13
|
+
const tutorialSiteRoot = path.join(tempRoot, 'my-site');
|
|
14
|
+
|
|
15
|
+
const runCli = (args) => spawnSync(process.execPath, [cliPath, ...args], {
|
|
16
|
+
cwd: repoRoot,
|
|
17
|
+
encoding: 'utf8',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const assertSuccess = (result, label) => {
|
|
21
|
+
assert.equal(result.status, 0, `${label} failed:\n${result.stderr || result.stdout}`);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const extractTutorialFile = (source, label, language) => {
|
|
25
|
+
const escapedLabel = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
26
|
+
const pattern = new RegExp(`${escapedLabel}\\n\\n\\x60{3}${language}\\n([\\s\\S]*?)\\n\\x60{3}`);
|
|
27
|
+
const match = source.match(pattern);
|
|
28
|
+
assert.ok(match, `Could not find the ${label} code block in docs/getting-started.md.`);
|
|
29
|
+
return `${match[1]}\n`;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const collectMarkdownFiles = async (directory) => {
|
|
33
|
+
const files = [];
|
|
34
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
35
|
+
const entryPath = path.join(directory, entry.name);
|
|
36
|
+
if (entry.isDirectory()) {
|
|
37
|
+
files.push(...await collectMarkdownFiles(entryPath));
|
|
38
|
+
} else if (entry.name.endsWith('.md')) {
|
|
39
|
+
files.push(entryPath);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return files;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const checkLocalMarkdownLinks = async () => {
|
|
46
|
+
const markdownFiles = [
|
|
47
|
+
path.join(repoRoot, 'README.md'),
|
|
48
|
+
...await collectMarkdownFiles(path.join(repoRoot, 'docs')),
|
|
49
|
+
...await collectMarkdownFiles(path.join(repoRoot, 'examples')),
|
|
50
|
+
];
|
|
51
|
+
const missing = [];
|
|
52
|
+
|
|
53
|
+
for (const markdownPath of markdownFiles) {
|
|
54
|
+
const source = await readFile(markdownPath, 'utf8');
|
|
55
|
+
const prose = source
|
|
56
|
+
.replace(/(```+|~~~+)[\s\S]*?\1/g, '')
|
|
57
|
+
.replace(/`[^`\n]*`/g, '');
|
|
58
|
+
for (const match of prose.matchAll(/!?\[[^\]]*\]\(([^)]+)\)/g)) {
|
|
59
|
+
const target = match[1].trim().replace(/^<|>$/g, '');
|
|
60
|
+
if (/^(?:[a-z]+:|#|\/)/i.test(target)) continue;
|
|
61
|
+
|
|
62
|
+
const targetPath = decodeURIComponent(target.split('#', 1)[0].split('?', 1)[0]);
|
|
63
|
+
if (!targetPath) continue;
|
|
64
|
+
const resolved = path.resolve(path.dirname(markdownPath), targetPath);
|
|
65
|
+
if (!existsSync(resolved)) {
|
|
66
|
+
missing.push(`${path.relative(repoRoot, markdownPath)} -> ${target}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
assert.deepEqual(missing, [], `Broken local Markdown links:\n${missing.join('\n')}`);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
const tutorial = await readFile(tutorialPath, 'utf8');
|
|
76
|
+
const initResult = runCli(['init', tutorialSiteRoot]);
|
|
77
|
+
assertSuccess(initResult, 'Tutorial init');
|
|
78
|
+
await rm(path.join(tutorialSiteRoot, 'node_modules'), { force: true, recursive: true });
|
|
79
|
+
await symlink(path.join(repoRoot, 'node_modules'), path.join(tutorialSiteRoot, 'node_modules'), 'dir');
|
|
80
|
+
|
|
81
|
+
await Promise.all([
|
|
82
|
+
writeFile(
|
|
83
|
+
path.join(tutorialSiteRoot, 'site', 'content.md'),
|
|
84
|
+
extractTutorialFile(tutorial, 'Replace `site/content.md` with:', 'md'),
|
|
85
|
+
),
|
|
86
|
+
writeFile(
|
|
87
|
+
path.join(tutorialSiteRoot, 'site', 'sitewide-content.md'),
|
|
88
|
+
extractTutorialFile(tutorial, 'Replace `site/sitewide-content.md` with:', 'yaml'),
|
|
89
|
+
),
|
|
90
|
+
writeFile(
|
|
91
|
+
path.join(tutorialSiteRoot, 'site', 'theme.md'),
|
|
92
|
+
extractTutorialFile(tutorial, 'Replace `site/theme.md` with:', 'yaml'),
|
|
93
|
+
),
|
|
94
|
+
]);
|
|
95
|
+
|
|
96
|
+
const siteDirectory = path.join(tutorialSiteRoot, 'site');
|
|
97
|
+
assertSuccess(runCli(['--site-dir', siteDirectory, 'config:check']), 'Tutorial config:check');
|
|
98
|
+
assertSuccess(runCli(['--site-dir', siteDirectory, 'content:check']), 'Tutorial content:check');
|
|
99
|
+
assertSuccess(runCli(['--site-dir', siteDirectory, 'build']), 'Tutorial build');
|
|
100
|
+
|
|
101
|
+
const html = await readFile(path.join(tutorialSiteRoot, 'dist', 'index.html'), 'utf8');
|
|
102
|
+
assert.match(html, /My first Norna site/);
|
|
103
|
+
assert.match(html, /Welcome/);
|
|
104
|
+
assert.match(html, /Next/);
|
|
105
|
+
|
|
106
|
+
await checkLocalMarkdownLinks();
|
|
107
|
+
|
|
108
|
+
const llms = await readFile(path.join(repoRoot, 'site', 'public', 'llms.txt'), 'utf8');
|
|
109
|
+
for (const match of llms.matchAll(/https:\/\/raw\.githubusercontent\.com\/janga\/norna\/main\/([^\s)]+)/g)) {
|
|
110
|
+
assert.ok(existsSync(path.join(repoRoot, decodeURIComponent(match[1]))), `llms.txt target is missing: ${match[1]}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.log('ok - tutorial source builds and documentation links resolve');
|
|
114
|
+
} finally {
|
|
115
|
+
await rm(tempRoot, { force: true, recursive: true });
|
|
116
|
+
}
|
|
@@ -24,9 +24,18 @@ try {
|
|
|
24
24
|
assert.match(versionResult.stdout, new RegExp(`Installed norna: ${packageJson.version.replaceAll('.', '\\.')}`));
|
|
25
25
|
assert.match(versionResult.stdout, /Installed Astro: /);
|
|
26
26
|
|
|
27
|
+
const deployHelpResult = runCli(['deploy', '--help']);
|
|
28
|
+
assert.equal(deployHelpResult.status, 0, deployHelpResult.stderr || deployHelpResult.stdout);
|
|
29
|
+
assert.match(deployHelpResult.stdout, /already committed default branch/);
|
|
30
|
+
const deployWatchHelpResult = runCli(['deploy:watch', '--help']);
|
|
31
|
+
assert.equal(deployWatchHelpResult.status, 0, deployWatchHelpResult.stderr || deployWatchHelpResult.stdout);
|
|
32
|
+
assert.match(deployWatchHelpResult.stdout, /Default: current repository/);
|
|
33
|
+
assert.match(deployWatchHelpResult.stdout, /Default: repository default branch/);
|
|
34
|
+
assert.match(deployWatchHelpResult.stdout, /Default: deploy\.yml/);
|
|
35
|
+
|
|
27
36
|
const directSiteRoot = path.join(tempRoot, 'current-directory-site');
|
|
28
37
|
await mkdir(directSiteRoot, { recursive: true });
|
|
29
|
-
await writeFile(path.join(directSiteRoot, 'config.
|
|
38
|
+
await writeFile(path.join(directSiteRoot, 'config.md'), '---\nurl: https://example.com/\n---\n');
|
|
30
39
|
await writeFile(path.join(directSiteRoot, 'content.md'), '---\ntitle: Direct Site\ndescription: Direct site fixture.\n---\n\n## Intro {#intro}\n\nText.\n');
|
|
31
40
|
const directSiteProjectRoot = await realpath(tempRoot);
|
|
32
41
|
const directSiteDoctorResult = runCli(['doctor'], {
|
|
@@ -45,6 +54,7 @@ try {
|
|
|
45
54
|
assert.equal(initializedPackageJson.dependencies['@janga/norna'], packageJson.version);
|
|
46
55
|
assert.equal(initializedPackageJson.scripts['norna:engine:update'], 'norna engine:update');
|
|
47
56
|
assert.equal(initializedPackageJson.scripts['norna:engine:version'], 'norna engine:version');
|
|
57
|
+
assert.equal(initializedPackageJson.scripts['norna:theme:export'], 'norna theme:export');
|
|
48
58
|
assert.equal(initializedPackageJson.scripts['engine:update'], undefined);
|
|
49
59
|
assert.equal(initializedPackageJson.scripts['engine:version'], undefined);
|
|
50
60
|
|
|
@@ -94,7 +104,7 @@ try {
|
|
|
94
104
|
assert.equal(customPurePackageJson.scripts['norna:dev'], 'norna --site-dir presentation dev:local');
|
|
95
105
|
assert.equal(customPurePackageJson.scripts['norna:build'], 'norna --site-dir presentation build');
|
|
96
106
|
await readFile(path.join(customPureSiteRoot, 'presentation', 'content.md'));
|
|
97
|
-
await readFile(path.join(customPureSiteRoot, 'presentation', 'config.
|
|
107
|
+
await readFile(path.join(customPureSiteRoot, 'presentation', 'config.md'));
|
|
98
108
|
await readFile(path.join(customPureSiteRoot, 'presentation', 'theme.md'));
|
|
99
109
|
|
|
100
110
|
const mixedProjectRoot = path.join(tempRoot, 'mixed-project');
|
|
@@ -120,7 +130,7 @@ try {
|
|
|
120
130
|
assert.equal(mixedPackageJson.scripts['norna:engine:update'], 'norna --site-dir presentation engine:update');
|
|
121
131
|
assert.equal(mixedPackageJson.scripts['norna:engine:version'], 'norna --site-dir presentation engine:version');
|
|
122
132
|
await readFile(path.join(mixedProjectRoot, 'presentation', 'content.md'));
|
|
123
|
-
await readFile(path.join(mixedProjectRoot, 'presentation', 'config.
|
|
133
|
+
await readFile(path.join(mixedProjectRoot, 'presentation', 'config.md'));
|
|
124
134
|
await readFile(path.join(mixedProjectRoot, 'presentation', 'theme.md'));
|
|
125
135
|
|
|
126
136
|
const conflictProjectRoot = path.join(tempRoot, 'conflict-project');
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { getExampleSites } from './lib/example-sites.mjs';
|
|
6
|
+
import { runInherit } from './lib/run-command.mjs';
|
|
7
|
+
|
|
8
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
|
+
const cliPath = path.join(root, 'bin', 'norna.mjs');
|
|
10
|
+
const examples = await getExampleSites(root);
|
|
11
|
+
|
|
12
|
+
for (const example of examples) {
|
|
13
|
+
console.log(`\nBuilding ${example.siteLabel}`);
|
|
14
|
+
await runInherit(process.execPath, [cliPath, '--site-dir', example.siteLabel, 'build'], { cwd: root });
|
|
15
|
+
|
|
16
|
+
if (['svg', 'png', 'jpg', 'jpeg'].some((extension) => existsSync(path.join(example.siteDirectory, 'public', `logo.${extension}`)))) {
|
|
17
|
+
const homepageHtml = await readFile(path.join(root, 'dist', 'index.html'), 'utf8');
|
|
18
|
+
if (!homepageHtml.includes('class="site-brand-logo"')) {
|
|
19
|
+
throw new Error(`Example ${example.siteLabel} has a logo file that is not rendered on its homepage.`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log(`\nok - built ${examples.length} example sites`);
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import net from 'node:net';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { promisify } from 'node:util';
|
|
5
|
-
|
|
6
|
-
const execFileAsync = promisify(execFile);
|
|
7
5
|
|
|
8
6
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
9
7
|
const cliPath = path.join(root, 'bin', 'norna.mjs');
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const probeUrls = [url, 'http://127.0.0.1:4321/', 'http://[::1]:4321/'];
|
|
8
|
+
const navigationDemoSiteDir = path.join(root, 'examples', 'feature-demos', 'media-and-surfaces', 'site');
|
|
9
|
+
const host = '127.0.0.1';
|
|
13
10
|
const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
14
11
|
const testTargets = process.argv.slice(2);
|
|
15
12
|
const playwrightTargets = testTargets.length > 0 ? testTargets : ['tests/navigation.spec.ts'];
|
|
@@ -18,33 +15,46 @@ const sleep = (milliseconds) => new Promise((resolve) => {
|
|
|
18
15
|
setTimeout(resolve, milliseconds);
|
|
19
16
|
});
|
|
20
17
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
18
|
+
const getAvailablePort = () => new Promise((resolve, reject) => {
|
|
19
|
+
const server = net.createServer();
|
|
20
|
+
server.unref();
|
|
21
|
+
server.once('error', reject);
|
|
22
|
+
server.listen(0, host, () => {
|
|
23
|
+
const address = server.address();
|
|
24
|
+
const port = typeof address === 'object' && address ? address.port : null;
|
|
25
|
+
server.close((error) => {
|
|
26
|
+
if (error) {
|
|
27
|
+
reject(error);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
resolve(port);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const port = await getAvailablePort();
|
|
36
|
+
if (!port) throw new Error('Could not reserve a port for the navigation test server.');
|
|
37
|
+
const url = `http://${host}:${port}/`;
|
|
31
38
|
|
|
39
|
+
const isReachable = async () => {
|
|
32
40
|
try {
|
|
33
|
-
await
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
});
|
|
37
|
-
return true;
|
|
41
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(1_000) });
|
|
42
|
+
await response.arrayBuffer();
|
|
43
|
+
return response.ok;
|
|
38
44
|
} catch {
|
|
39
45
|
return false;
|
|
40
46
|
}
|
|
41
47
|
};
|
|
42
48
|
|
|
43
|
-
const waitForServer = async () => {
|
|
49
|
+
const waitForServer = async (serverProcess) => {
|
|
44
50
|
const startedAt = Date.now();
|
|
45
51
|
const timeoutMs = 30_000;
|
|
46
52
|
|
|
47
53
|
while (Date.now() - startedAt < timeoutMs) {
|
|
54
|
+
if (serverProcess.exitCode !== null) {
|
|
55
|
+
throw new Error(`Navigation test server exited before ${url} became reachable.`);
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
if (await isReachable()) {
|
|
49
59
|
return;
|
|
50
60
|
}
|
|
@@ -55,12 +65,6 @@ const waitForServer = async () => {
|
|
|
55
65
|
throw new Error(`Timed out waiting for ${url}`);
|
|
56
66
|
};
|
|
57
67
|
|
|
58
|
-
const runCapture = async (command, args, options = {}) => execFileAsync(command, args, {
|
|
59
|
-
cwd: root,
|
|
60
|
-
maxBuffer: 1024 * 1024 * 10,
|
|
61
|
-
...options,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
68
|
const runInherit = (command, args, options = {}) => new Promise((resolve, reject) => {
|
|
65
69
|
const child = spawn(command, args, {
|
|
66
70
|
cwd: root,
|
|
@@ -82,31 +86,57 @@ const runInherit = (command, args, options = {}) => new Promise((resolve, reject
|
|
|
82
86
|
});
|
|
83
87
|
});
|
|
84
88
|
|
|
85
|
-
const
|
|
86
|
-
await
|
|
89
|
+
const startServer = async () => {
|
|
90
|
+
await runInherit(process.execPath, [cliPath, 'site:public'], {
|
|
91
|
+
cwd: navigationDemoSiteDir,
|
|
92
|
+
});
|
|
93
|
+
await runInherit(process.execPath, [cliPath, 'images'], {
|
|
94
|
+
cwd: navigationDemoSiteDir,
|
|
95
|
+
});
|
|
87
96
|
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
const serverProcess = spawn(process.execPath, [
|
|
98
|
+
cliPath,
|
|
99
|
+
'astro',
|
|
100
|
+
'dev',
|
|
101
|
+
'--ignore-lock',
|
|
102
|
+
'--host',
|
|
103
|
+
host,
|
|
104
|
+
'--port',
|
|
105
|
+
String(port),
|
|
106
|
+
], {
|
|
107
|
+
cwd: navigationDemoSiteDir,
|
|
108
|
+
stdio: 'inherit',
|
|
90
109
|
env: {
|
|
91
110
|
...process.env,
|
|
92
|
-
|
|
111
|
+
ASTRO_DEV_BACKGROUND: '0',
|
|
93
112
|
},
|
|
94
113
|
});
|
|
95
|
-
|
|
114
|
+
serverProcess.once('error', (error) => {
|
|
115
|
+
throw error;
|
|
116
|
+
});
|
|
117
|
+
await waitForServer(serverProcess);
|
|
96
118
|
|
|
97
|
-
return
|
|
119
|
+
return serverProcess;
|
|
98
120
|
};
|
|
99
121
|
|
|
100
|
-
const stopServer = async () => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
122
|
+
const stopServer = async (serverProcess) => {
|
|
123
|
+
if (!serverProcess || serverProcess.exitCode !== null) return;
|
|
124
|
+
|
|
125
|
+
serverProcess.kill('SIGTERM');
|
|
126
|
+
const stopped = await Promise.race([
|
|
127
|
+
new Promise((resolve) => serverProcess.once('exit', () => resolve(true))),
|
|
128
|
+
sleep(5_000).then(() => false),
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
if (!stopped && serverProcess.exitCode === null) {
|
|
132
|
+
serverProcess.kill('SIGKILL');
|
|
133
|
+
}
|
|
104
134
|
};
|
|
105
135
|
|
|
106
|
-
let
|
|
136
|
+
let serverProcess;
|
|
107
137
|
|
|
108
138
|
try {
|
|
109
|
-
|
|
139
|
+
serverProcess = await startServer();
|
|
110
140
|
await runInherit(npmBin, ['exec', '--', 'playwright', 'test', ...playwrightTargets], {
|
|
111
141
|
env: {
|
|
112
142
|
...process.env,
|
|
@@ -114,7 +144,5 @@ try {
|
|
|
114
144
|
},
|
|
115
145
|
});
|
|
116
146
|
} finally {
|
|
117
|
-
|
|
118
|
-
await stopServer();
|
|
119
|
-
}
|
|
147
|
+
await stopServer(serverProcess);
|
|
120
148
|
}
|
|
@@ -158,12 +158,13 @@ try {
|
|
|
158
158
|
assertFileExists(path.join(packagedStarterRoot, '.github', 'workflows', 'deploy.yml')),
|
|
159
159
|
assertFileExists(path.join(packagedStarterRoot, 'package.json')),
|
|
160
160
|
assertFileExists(path.join(packagedStarterRoot, 'README.md')),
|
|
161
|
-
assertFileExists(path.join(packagedStarterRoot, 'site', 'config.
|
|
161
|
+
assertFileExists(path.join(packagedStarterRoot, 'site', 'config.md')),
|
|
162
162
|
assertFileExists(path.join(packagedStarterRoot, 'site', 'theme.md')),
|
|
163
163
|
assertFileExists(path.join(packagedStarterRoot, 'site', 'sitewide-content.md')),
|
|
164
164
|
assertFileExists(path.join(packagedStarterRoot, 'site', 'content.md')),
|
|
165
165
|
assertFileExists(path.join(packagedStarterRoot, 'site', 'images', 'work', '.gitkeep')),
|
|
166
166
|
assertFileExists(path.join(packagedStarterRoot, 'site', 'public', 'robots.txt')),
|
|
167
|
+
assertFileMissing(path.join(packagedStarterRoot, 'site', 'config.mjs')),
|
|
167
168
|
]);
|
|
168
169
|
await assertFileIncludes(
|
|
169
170
|
path.join(packagedStarterRoot, '.github', 'workflows', 'deploy.yml'),
|
|
@@ -177,13 +178,11 @@ try {
|
|
|
177
178
|
packageJson.name = 'norna-package-check-site';
|
|
178
179
|
packageJson.dependencies['@janga/norna'] = tarballPath;
|
|
179
180
|
await writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
|
|
180
|
-
const packageCheckConfigPath = path.join(siteProjectRoot, 'site', 'config.
|
|
181
|
+
const packageCheckConfigPath = path.join(siteProjectRoot, 'site', 'config.md');
|
|
181
182
|
const packageCheckConfig = await readFile(packageCheckConfigPath, 'utf8');
|
|
182
183
|
await writeFile(
|
|
183
184
|
packageCheckConfigPath,
|
|
184
|
-
packageCheckConfig
|
|
185
|
-
.replace("url: 'https://example.com/'", "url: 'https://example.com/site/'")
|
|
186
|
-
.replace("basePath: '/'", "basePath: '/site/'"),
|
|
185
|
+
packageCheckConfig.replace('url: https://example.com/', 'url: https://example.com/site/'),
|
|
187
186
|
);
|
|
188
187
|
const packageCheckSitewidePath = path.join(siteProjectRoot, 'site', 'sitewide-content.md');
|
|
189
188
|
const packageCheckSitewide = await readFile(packageCheckSitewidePath, 'utf8');
|
|
@@ -241,10 +240,11 @@ This route verifies that packaged norna sites can build route pages.
|
|
|
241
240
|
await runInherit(nornaBinPath, ['init', initializedSiteRoot], { cwd: tempRoot, env: npmEnv });
|
|
242
241
|
await Promise.all([
|
|
243
242
|
assertFileExists(path.join(initializedSiteRoot, 'package.json')),
|
|
244
|
-
assertFileExists(path.join(initializedSiteRoot, 'site', 'config.
|
|
243
|
+
assertFileExists(path.join(initializedSiteRoot, 'site', 'config.md')),
|
|
245
244
|
assertFileExists(path.join(initializedSiteRoot, 'site', 'theme.md')),
|
|
246
245
|
assertFileMissing(path.join(initializedSiteRoot, '.DS_Store')),
|
|
247
246
|
assertFileMissing(path.join(initializedSiteRoot, 'site', '.DS_Store')),
|
|
247
|
+
assertFileMissing(path.join(initializedSiteRoot, 'site', 'config.mjs')),
|
|
248
248
|
]);
|
|
249
249
|
await runInherit(npxBin, ['norna', 'engine:version'], { cwd: path.join(siteProjectRoot, 'site', 'images', 'work'), env: npmEnv });
|
|
250
250
|
await runInherit(npxBin, ['norna', 'doctor'], { cwd: path.join(siteProjectRoot, 'site', 'images', 'work'), env: npmEnv });
|
|
@@ -287,6 +287,14 @@ This route verifies that packaged norna sites can build route pages.
|
|
|
287
287
|
path.join(siteProjectRoot, 'dist', 'index.html'),
|
|
288
288
|
'<meta name="format-detection" content="telephone=no">',
|
|
289
289
|
);
|
|
290
|
+
await assertFileIncludes(
|
|
291
|
+
path.join(siteProjectRoot, 'dist', 'index.html'),
|
|
292
|
+
'style="scroll-behavior: auto;',
|
|
293
|
+
);
|
|
294
|
+
await assertFileExcludes(
|
|
295
|
+
path.join(siteProjectRoot, 'dist', 'index.html'),
|
|
296
|
+
'data-smooth-scroll=',
|
|
297
|
+
);
|
|
290
298
|
await assertFileIncludes(
|
|
291
299
|
path.join(siteProjectRoot, 'dist', 'about', 'index.html'),
|
|
292
300
|
'<link rel="canonical" href="https://example.com/site/about/">',
|
|
@@ -506,17 +514,17 @@ This route verifies that packaged norna sites can build route pages.
|
|
|
506
514
|
'typography.fontFamily',
|
|
507
515
|
);
|
|
508
516
|
await writeFile(siteThemePath, siteTheme);
|
|
509
|
-
const siteConfigPath = path.join(siteProjectRoot, 'site', 'config.
|
|
517
|
+
const siteConfigPath = path.join(siteProjectRoot, 'site', 'config.md');
|
|
510
518
|
const siteConfig = await readFile(siteConfigPath, 'utf8');
|
|
511
519
|
await writeFile(
|
|
512
520
|
siteConfigPath,
|
|
513
|
-
siteConfig.replace(
|
|
521
|
+
siteConfig.replace('url: https://example.com/site/', 'url: example.com/site/'),
|
|
514
522
|
);
|
|
515
523
|
await runExpectFailure(
|
|
516
524
|
npxBin,
|
|
517
525
|
['norna', 'config:check'],
|
|
518
526
|
{ cwd: siteProjectRoot, env: npmEnv },
|
|
519
|
-
'
|
|
527
|
+
'url must be an absolute URL',
|
|
520
528
|
);
|
|
521
529
|
|
|
522
530
|
console.log('Package check passed.');
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const repoRoot = path.resolve(import.meta.dirname, '..');
|
|
9
|
+
const projectConfigUrl = pathToFileURL(path.join(repoRoot, 'scripts', 'lib', 'project-config.mjs')).href;
|
|
10
|
+
const tempRoot = await mkdtemp(path.join(tmpdir(), 'norna-project-config-'));
|
|
11
|
+
const importScript = `
|
|
12
|
+
const { projectConfig } = await import(${JSON.stringify(projectConfigUrl)});
|
|
13
|
+
console.log(JSON.stringify({
|
|
14
|
+
basePath: projectConfig.site.basePath,
|
|
15
|
+
language: projectConfig.locale.lang,
|
|
16
|
+
labels: projectConfig.locale.labels,
|
|
17
|
+
scrollBehavior: projectConfig.navigation.scrollBehavior,
|
|
18
|
+
url: projectConfig.site.url,
|
|
19
|
+
}));
|
|
20
|
+
`;
|
|
21
|
+
|
|
22
|
+
const createSite = async (name, config, { legacy = false } = {}) => {
|
|
23
|
+
const projectRoot = path.join(tempRoot, name);
|
|
24
|
+
const siteDir = path.join(projectRoot, 'site');
|
|
25
|
+
await mkdir(siteDir, { recursive: true });
|
|
26
|
+
await writeFile(path.join(siteDir, legacy ? 'config.mjs' : 'config.md'), config);
|
|
27
|
+
await writeFile(path.join(siteDir, 'content.md'), '---\ntitle: Config test\ndescription: Config test.\n---\n\n## Intro {#intro}\n\nText.\n');
|
|
28
|
+
await writeFile(path.join(siteDir, 'theme.md'), '---\npreset: documentation\n---\n');
|
|
29
|
+
return { projectRoot, siteDir };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const loadConfig = ({ projectRoot, siteDir }, env = {}) => spawnSync(
|
|
33
|
+
process.execPath,
|
|
34
|
+
['--input-type=module', '--eval', importScript],
|
|
35
|
+
{
|
|
36
|
+
cwd: projectRoot,
|
|
37
|
+
encoding: 'utf8',
|
|
38
|
+
env: {
|
|
39
|
+
...process.env,
|
|
40
|
+
NORNA_INVOCATION_ROOT: projectRoot,
|
|
41
|
+
NORNA_SITE_DIR: siteDir,
|
|
42
|
+
...env,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const assertFailure = (result, expectedPattern) => {
|
|
48
|
+
assert.notEqual(result.status, 0, result.stdout);
|
|
49
|
+
assert.match(`${result.stdout}\n${result.stderr}`, expectedPattern);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const minimalSite = await createSite('minimal', '---\nurl: https://example.com/docs\n---\n');
|
|
54
|
+
const minimalResult = loadConfig(minimalSite);
|
|
55
|
+
assert.equal(minimalResult.status, 0, minimalResult.stderr);
|
|
56
|
+
assert.deepEqual(JSON.parse(minimalResult.stdout), {
|
|
57
|
+
basePath: '/docs/',
|
|
58
|
+
language: 'en',
|
|
59
|
+
labels: {
|
|
60
|
+
dismissBanner: 'Dismiss notice',
|
|
61
|
+
gallery: 'Images',
|
|
62
|
+
note: 'Note',
|
|
63
|
+
pageNavigation: 'On this page',
|
|
64
|
+
siteBanners: 'Site notices',
|
|
65
|
+
siteNavigation: 'Pages',
|
|
66
|
+
skipToContent: 'Skip to content',
|
|
67
|
+
},
|
|
68
|
+
scrollBehavior: 'instant',
|
|
69
|
+
url: 'https://example.com/docs/',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const localizedSite = await createSite('localized', '---\nurl: https://example.com/\nlanguage: sv-SE\nscrollBehavior: browser-smooth\n---\n');
|
|
73
|
+
const localizedResult = loadConfig(localizedSite);
|
|
74
|
+
assert.equal(localizedResult.status, 0, localizedResult.stderr);
|
|
75
|
+
const localizedConfig = JSON.parse(localizedResult.stdout);
|
|
76
|
+
assert.equal(localizedConfig.language, 'sv-SE');
|
|
77
|
+
assert.equal(localizedConfig.labels.skipToContent, 'Hoppa till innehållet');
|
|
78
|
+
assert.equal(localizedConfig.scrollBehavior, 'browser-smooth');
|
|
79
|
+
|
|
80
|
+
const nornaSmoothSite = await createSite('norna-smooth', '---\nurl: https://example.com/\nscrollBehavior: norna-smooth\n---\n');
|
|
81
|
+
const nornaSmoothResult = loadConfig(nornaSmoothSite);
|
|
82
|
+
assert.equal(nornaSmoothResult.status, 0, nornaSmoothResult.stderr);
|
|
83
|
+
assert.equal(JSON.parse(nornaSmoothResult.stdout).scrollBehavior, 'norna-smooth');
|
|
84
|
+
|
|
85
|
+
const overrideResult = loadConfig(minimalSite, {
|
|
86
|
+
NORNA_SITE_URL: 'http://127.0.0.1:4567/preview',
|
|
87
|
+
});
|
|
88
|
+
assert.equal(overrideResult.status, 0, overrideResult.stderr);
|
|
89
|
+
assert.deepEqual(
|
|
90
|
+
JSON.parse(overrideResult.stdout),
|
|
91
|
+
{
|
|
92
|
+
...JSON.parse(minimalResult.stdout),
|
|
93
|
+
basePath: '/preview/',
|
|
94
|
+
url: 'http://127.0.0.1:4567/preview/',
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
assertFailure(
|
|
99
|
+
loadConfig(await createSite('unknown-field', '---\nurl: https://example.com/\nbasePath: /docs/\n---\n')),
|
|
100
|
+
/not a valid top-level config field/,
|
|
101
|
+
);
|
|
102
|
+
assertFailure(
|
|
103
|
+
loadConfig(await createSite('markdown-body', '---\nurl: https://example.com/\n---\n\nConfiguration prose.\n')),
|
|
104
|
+
/may contain YAML frontmatter only/,
|
|
105
|
+
);
|
|
106
|
+
assertFailure(
|
|
107
|
+
loadConfig(await createSite('unsupported-language', '---\nurl: https://example.com/\nlanguage: de\n---\n')),
|
|
108
|
+
/has no built-in Norna UI text/,
|
|
109
|
+
);
|
|
110
|
+
assertFailure(
|
|
111
|
+
loadConfig(await createSite('invalid-url', '---\nurl: example.com\n---\n')),
|
|
112
|
+
/url must be an absolute URL/,
|
|
113
|
+
);
|
|
114
|
+
assertFailure(
|
|
115
|
+
loadConfig(await createSite('invalid-scroll-behavior', '---\nurl: https://example.com/\nscrollBehavior: slow\n---\n')),
|
|
116
|
+
/scrollBehavior must be one of instant, browser-smooth, norna-smooth/,
|
|
117
|
+
);
|
|
118
|
+
assertFailure(
|
|
119
|
+
loadConfig(await createSite('obsolete-smooth-scroll', '---\nurl: https://example.com/\nsmoothScroll: true\n---\n')),
|
|
120
|
+
/not a valid top-level config field/,
|
|
121
|
+
);
|
|
122
|
+
assertFailure(
|
|
123
|
+
loadConfig(await createSite('legacy', 'export default {};\n', { legacy: true })),
|
|
124
|
+
/Replace the obsolete config\.mjs with a frontmatter-only config\.md file/,
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
console.log('Project config test passed.');
|
|
128
|
+
} finally {
|
|
129
|
+
await rm(tempRoot, { force: true, recursive: true });
|
|
130
|
+
}
|
|
@@ -37,16 +37,9 @@ try {
|
|
|
37
37
|
await mkdir(path.join(siteDir, 'images', 'work'), { recursive: true });
|
|
38
38
|
await mkdir(path.join(siteDir, 'public'), { recursive: true });
|
|
39
39
|
await writeFile(path.join(siteDir, 'public', 'robots.txt'), 'User-agent: *\nAllow: /\n');
|
|
40
|
-
await writeFile(path.join(siteDir, 'config.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
},
|
|
44
|
-
github: {
|
|
45
|
-
repo: 'owner/example',
|
|
46
|
-
branch: 'main',
|
|
47
|
-
pagesWorkflow: 'Deploy to GitHub Pages',
|
|
48
|
-
},
|
|
49
|
-
};
|
|
40
|
+
await writeFile(path.join(siteDir, 'config.md'), `---
|
|
41
|
+
url: https://example.com/
|
|
42
|
+
---
|
|
50
43
|
`);
|
|
51
44
|
await writeFile(path.join(siteDir, 'theme.md'), `---
|
|
52
45
|
typography:
|