@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
|
@@ -20,9 +20,10 @@ const h2Regex = /^##\s+.*$/gm;
|
|
|
20
20
|
const explicitHeadingIdRegex = /\s*\{#([a-z0-9-]+)\}\s*$/;
|
|
21
21
|
const deprecatedInlineStyleReferenceRegex = /\[[^\]\n]+\]\{\.([a-z][a-z0-9-]*)\}/g;
|
|
22
22
|
const frontmatterDelimiterRegex = /^---\s*$/;
|
|
23
|
+
const knownConfigTopLevelFrontmatterKeys = new Set(['url', 'language', 'scrollBehavior']);
|
|
23
24
|
const knownContentTopLevelFrontmatterKeys = new Set(['title', 'description', 'navigation', 'sections']);
|
|
24
|
-
const knownThemeTopLevelFrontmatterKeys = new Set(['navigation', 'layout', 'gallery', 'typography', 'presentation']);
|
|
25
|
-
const knownRouteThemeTopLevelFrontmatterKeys = new Set(['navigation', 'layout', 'gallery', 'typography', 'presentation']);
|
|
25
|
+
const knownThemeTopLevelFrontmatterKeys = new Set(['navigation', 'preset', 'layout', 'gallery', 'typography', 'presentation']);
|
|
26
|
+
const knownRouteThemeTopLevelFrontmatterKeys = new Set(['navigation', 'preset', 'layout', 'gallery', 'typography', 'presentation']);
|
|
26
27
|
const knownSitewideTopLevelFrontmatterKeys = new Set(['navigation', 'banners', 'footer']);
|
|
27
28
|
const knownNestedFrontmatterKeys = new Set([
|
|
28
29
|
'align',
|
|
@@ -270,6 +271,12 @@ export const validateContentFrontmatterStructure = (frontmatter, addIssue) =>
|
|
|
270
271
|
fileKind: 'content',
|
|
271
272
|
});
|
|
272
273
|
|
|
274
|
+
export const validateConfigFrontmatterStructure = (frontmatter, addIssue) =>
|
|
275
|
+
validateFrontmatterStructure(frontmatter, addIssue, {
|
|
276
|
+
knownTopLevelFrontmatterKeys: knownConfigTopLevelFrontmatterKeys,
|
|
277
|
+
fileKind: 'config',
|
|
278
|
+
});
|
|
279
|
+
|
|
273
280
|
export const validateThemeFrontmatterStructure = (frontmatter, addIssue) =>
|
|
274
281
|
validateFrontmatterStructure(frontmatter, addIssue, {
|
|
275
282
|
knownTopLevelFrontmatterKeys: knownThemeTopLevelFrontmatterKeys,
|
|
@@ -22,7 +22,10 @@ export const invocationRoot = configuredInvocationRoot
|
|
|
22
22
|
|
|
23
23
|
const hasSiteFilesInDirectory = (siteDir) => {
|
|
24
24
|
return (
|
|
25
|
-
|
|
25
|
+
(
|
|
26
|
+
existsSync(path.join(siteDir, 'config.md'))
|
|
27
|
+
|| existsSync(path.join(siteDir, 'config.mjs'))
|
|
28
|
+
)
|
|
26
29
|
&& existsSync(path.join(siteDir, 'content.md'))
|
|
27
30
|
);
|
|
28
31
|
};
|
|
@@ -114,7 +117,8 @@ const getPathLabel = (filePath) => {
|
|
|
114
117
|
};
|
|
115
118
|
|
|
116
119
|
export const siteDir = resolvedSitePaths.siteDir;
|
|
117
|
-
export const siteConfigPath = path.join(siteDir, 'config.
|
|
120
|
+
export const siteConfigPath = path.join(siteDir, 'config.md');
|
|
121
|
+
export const legacySiteConfigPath = path.join(siteDir, 'config.mjs');
|
|
118
122
|
export const siteThemePath = path.join(siteDir, 'theme.md');
|
|
119
123
|
export const siteContentPath = path.join(siteDir, 'content.md');
|
|
120
124
|
export const sitewideContentPath = path.join(siteDir, 'sitewide-content.md');
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
siteThemePath,
|
|
15
15
|
sitewideContentLabel,
|
|
16
16
|
} from './site-paths.mjs';
|
|
17
|
+
import { resolveThemeConfig } from './theme-presets.mjs';
|
|
17
18
|
|
|
18
19
|
export const readThemeConfig = async () => {
|
|
19
20
|
const themeFile = await readFile(siteThemePath, 'utf8').catch((error) => {
|
|
@@ -40,6 +41,7 @@ export const readThemeConfig = async () => {
|
|
|
40
41
|
if (Object.hasOwn(config, 'navigation')) {
|
|
41
42
|
throw new Error(`${siteThemeLabel} may not define navigation. Brand and logo belong in ${sitewideContentLabel}.`);
|
|
42
43
|
}
|
|
44
|
+
resolveThemeConfig(config, siteThemeLabel);
|
|
43
45
|
|
|
44
46
|
return config;
|
|
45
47
|
};
|
|
@@ -92,6 +94,7 @@ export const validateRouteThemeFiles = async () => {
|
|
|
92
94
|
if (Object.hasOwn(config, 'navigation')) {
|
|
93
95
|
throw new Error(`${file.label} may not define navigation. Brand and logo belong in ${sitewideContentLabel}.`);
|
|
94
96
|
}
|
|
97
|
+
resolveThemeConfig(config, file.label);
|
|
95
98
|
|
|
96
99
|
configs.push({ ...file, config });
|
|
97
100
|
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { mergeDeep } from './typography.mjs';
|
|
2
|
+
|
|
3
|
+
export const themePresetNames = [
|
|
4
|
+
'portfolio',
|
|
5
|
+
'documentation',
|
|
6
|
+
'project',
|
|
7
|
+
'statement',
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
export const themePresets = Object.freeze({
|
|
11
|
+
portfolio: Object.freeze({
|
|
12
|
+
layout: {
|
|
13
|
+
density: 'normal',
|
|
14
|
+
pageWidth: '1240px',
|
|
15
|
+
gutter: {
|
|
16
|
+
desktop: 'clamp(1.25rem, 4vw, 3rem)',
|
|
17
|
+
mobile: '1rem',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
gallery: {
|
|
21
|
+
width: '1000px',
|
|
22
|
+
maxAvailableWidthPercent: { desktop: 100, mobile: 100 },
|
|
23
|
+
maxAvailableHeightPercent: { desktop: 78, mobile: 68 },
|
|
24
|
+
},
|
|
25
|
+
typography: {
|
|
26
|
+
fontFamily: "'Helvetica Neue', Arial, sans-serif",
|
|
27
|
+
preset: 'quiet-gallery',
|
|
28
|
+
rhythm: 'normal',
|
|
29
|
+
},
|
|
30
|
+
presentation: {
|
|
31
|
+
palette: 'dark',
|
|
32
|
+
sectionSurfaces: {
|
|
33
|
+
mode: 'none',
|
|
34
|
+
sequence: ['base', 'soft', 'emphasis'],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
documentation: Object.freeze({
|
|
39
|
+
layout: {
|
|
40
|
+
density: 'compact',
|
|
41
|
+
pageWidth: '1240px',
|
|
42
|
+
gutter: {
|
|
43
|
+
desktop: 'clamp(1.25rem, 4vw, 3rem)',
|
|
44
|
+
mobile: '1rem',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
gallery: {
|
|
48
|
+
width: '920px',
|
|
49
|
+
maxAvailableWidthPercent: { desktop: 100, mobile: 100 },
|
|
50
|
+
maxAvailableHeightPercent: { desktop: 74, mobile: 68 },
|
|
51
|
+
},
|
|
52
|
+
typography: {
|
|
53
|
+
fontFamily: "Georgia, 'Times New Roman', serif",
|
|
54
|
+
preset: 'text-forward',
|
|
55
|
+
rhythm: 'compact',
|
|
56
|
+
},
|
|
57
|
+
presentation: {
|
|
58
|
+
palette: 'paper',
|
|
59
|
+
sectionSurfaces: {
|
|
60
|
+
mode: 'cycle',
|
|
61
|
+
sequence: ['base', 'soft'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
project: Object.freeze({
|
|
66
|
+
layout: {
|
|
67
|
+
density: 'compact',
|
|
68
|
+
pageWidth: '1120px',
|
|
69
|
+
gutter: {
|
|
70
|
+
desktop: 'clamp(1.25rem, 4vw, 3rem)',
|
|
71
|
+
mobile: '1rem',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
gallery: {
|
|
75
|
+
width: '840px',
|
|
76
|
+
maxAvailableWidthPercent: { desktop: 100, mobile: 100 },
|
|
77
|
+
maxAvailableHeightPercent: { desktop: 70, mobile: 62 },
|
|
78
|
+
},
|
|
79
|
+
typography: {
|
|
80
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
81
|
+
preset: 'text-forward',
|
|
82
|
+
rhythm: 'compact',
|
|
83
|
+
},
|
|
84
|
+
presentation: {
|
|
85
|
+
palette: 'light',
|
|
86
|
+
sectionSurfaces: {
|
|
87
|
+
mode: 'cycle',
|
|
88
|
+
sequence: ['base', 'soft'],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
statement: Object.freeze({
|
|
93
|
+
layout: {
|
|
94
|
+
density: 'airy',
|
|
95
|
+
pageWidth: '1280px',
|
|
96
|
+
gutter: {
|
|
97
|
+
desktop: 'clamp(1.5rem, 5vw, 4rem)',
|
|
98
|
+
mobile: '1rem',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
gallery: {
|
|
102
|
+
width: '1080px',
|
|
103
|
+
maxAvailableWidthPercent: { desktop: 100, mobile: 100 },
|
|
104
|
+
maxAvailableHeightPercent: { desktop: 80, mobile: 70 },
|
|
105
|
+
},
|
|
106
|
+
typography: {
|
|
107
|
+
fontFamily: "'Trebuchet MS', 'Helvetica Neue', Arial, sans-serif",
|
|
108
|
+
preset: 'statement',
|
|
109
|
+
rhythm: 'airy',
|
|
110
|
+
},
|
|
111
|
+
presentation: {
|
|
112
|
+
palette: 'paper',
|
|
113
|
+
sectionSurfaces: {
|
|
114
|
+
mode: 'cycle',
|
|
115
|
+
sequence: ['base', 'emphasis'],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export const getThemePreset = (presetName, sourceLabel = 'theme.md') => {
|
|
122
|
+
const preset = themePresets[presetName];
|
|
123
|
+
|
|
124
|
+
if (!preset) {
|
|
125
|
+
throw new Error(`Unknown theme preset "${presetName}" in ${sourceLabel}. Use one of: ${themePresetNames.join(', ')}.`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return structuredClone(preset);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const resolveThemeConfig = (theme = {}, sourceLabel = 'theme.md') => {
|
|
132
|
+
const presetName = theme?.preset;
|
|
133
|
+
if (presetName === undefined) return structuredClone(theme ?? {});
|
|
134
|
+
|
|
135
|
+
const overrides = structuredClone(theme ?? {});
|
|
136
|
+
delete overrides.preset;
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
preset: presetName,
|
|
140
|
+
...mergeDeep(getThemePreset(presetName, sourceLabel), overrides),
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const quote = (value) => JSON.stringify(value);
|
|
145
|
+
const responsiveValueLines = (label, value, indent = 2) => {
|
|
146
|
+
const prefix = ' '.repeat(indent);
|
|
147
|
+
return [
|
|
148
|
+
`${prefix}${label}:`,
|
|
149
|
+
`${prefix} desktop: ${value.desktop}`,
|
|
150
|
+
`${prefix} mobile: ${value.mobile}`,
|
|
151
|
+
];
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export const renderThemePresetReference = (presetName, sourceLabel = 'theme.md') => {
|
|
155
|
+
const preset = getThemePreset(presetName, sourceLabel);
|
|
156
|
+
const { layout, gallery, typography, presentation } = preset;
|
|
157
|
+
|
|
158
|
+
return [
|
|
159
|
+
'---',
|
|
160
|
+
`# Original values for Norna's "${presetName}" theme preset.`,
|
|
161
|
+
'# This is a reference file. Norna only loads theme.md.',
|
|
162
|
+
'# Keep the preset in theme.md and copy only the values you want to override.',
|
|
163
|
+
`# Available theme presets: ${themePresetNames.join(', ')}.`,
|
|
164
|
+
`preset: ${presetName}`,
|
|
165
|
+
'',
|
|
166
|
+
'layout:',
|
|
167
|
+
' # Alternatives: compact, normal, airy.',
|
|
168
|
+
` density: ${layout.density}`,
|
|
169
|
+
' # Any positive CSS length, including px, rem, em, %, or clamp(...).',
|
|
170
|
+
` pageWidth: ${layout.pageWidth}`,
|
|
171
|
+
' gutter:',
|
|
172
|
+
` desktop: ${layout.gutter.desktop}`,
|
|
173
|
+
` mobile: ${layout.gutter.mobile}`,
|
|
174
|
+
' # Optional spacing overrides use blockGap, finalSectionBottom,',
|
|
175
|
+
' # firstSectionTop, headingToBlock, imageGap, and sectionGap.',
|
|
176
|
+
'',
|
|
177
|
+
'gallery:',
|
|
178
|
+
' # width accepts a positive CSS length.',
|
|
179
|
+
` width: ${gallery.width}`,
|
|
180
|
+
' # Percent values must be greater than 0 and at most 100.',
|
|
181
|
+
...responsiveValueLines('maxAvailableWidthPercent', gallery.maxAvailableWidthPercent),
|
|
182
|
+
...responsiveValueLines('maxAvailableHeightPercent', gallery.maxAvailableHeightPercent),
|
|
183
|
+
'',
|
|
184
|
+
'typography:',
|
|
185
|
+
' # Any valid CSS font-family stack without semicolons.',
|
|
186
|
+
` fontFamily: ${quote(typography.fontFamily)}`,
|
|
187
|
+
' # Alternatives: quiet-gallery, compact-gallery, text-forward, statement.',
|
|
188
|
+
` preset: ${typography.preset}`,
|
|
189
|
+
' # Alternatives: compact, normal, airy.',
|
|
190
|
+
` rhythm: ${typography.rhythm}`,
|
|
191
|
+
' # Fine-grained overrides can target headings.h1-h4, body, and caption.',
|
|
192
|
+
' # Example:',
|
|
193
|
+
' # overrides:',
|
|
194
|
+
' # headings:',
|
|
195
|
+
' # h2:',
|
|
196
|
+
' # size: large # small, medium, large, or xlarge',
|
|
197
|
+
'',
|
|
198
|
+
'presentation:',
|
|
199
|
+
' # Alternatives: dark, light, paper.',
|
|
200
|
+
` palette: ${presentation.palette}`,
|
|
201
|
+
' sectionSurfaces:',
|
|
202
|
+
' # Alternatives: none, cycle.',
|
|
203
|
+
` mode: ${presentation.sectionSurfaces.mode}`,
|
|
204
|
+
' # Use one to three unique values from: base, soft, emphasis.',
|
|
205
|
+
` sequence: [${presentation.sectionSurfaces.sequence.join(', ')}]`,
|
|
206
|
+
'---',
|
|
207
|
+
'',
|
|
208
|
+
].join('\n');
|
|
209
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { parseYamlMapping } from './lib/frontmatter-yaml.mjs';
|
|
4
4
|
import {
|
|
5
5
|
defaultTypography,
|
|
6
6
|
resolveTypographyConfig,
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
siteThemeLabel,
|
|
26
26
|
siteThemePath,
|
|
27
27
|
} from './lib/site-paths.mjs';
|
|
28
|
+
import { resolveThemeConfig } from './lib/theme-presets.mjs';
|
|
28
29
|
|
|
29
30
|
const mode = process.argv[2] ?? 'show';
|
|
30
31
|
|
|
@@ -204,8 +205,8 @@ const readThemeTypography = async () => {
|
|
|
204
205
|
].join('\n'));
|
|
205
206
|
}
|
|
206
207
|
|
|
207
|
-
const
|
|
208
|
-
const themeTypographyConfig =
|
|
208
|
+
const themeConfig = resolveThemeConfig(parseYamlMapping(themeFrontmatterBody), siteThemeLabel);
|
|
209
|
+
const themeTypographyConfig = themeConfig.typography;
|
|
209
210
|
return resolveAnnotatedTypographyConfig(themeTypographyConfig ?? defaultTypography, siteThemeLabel);
|
|
210
211
|
};
|
|
211
212
|
|
|
@@ -231,8 +232,8 @@ const readRouteThemeTypography = async (contentFile, themeTypography) => {
|
|
|
231
232
|
].join('\n'));
|
|
232
233
|
}
|
|
233
234
|
|
|
234
|
-
const
|
|
235
|
-
const typographyConfig =
|
|
235
|
+
const routeThemeConfig = resolveThemeConfig(parseYamlMapping(frontmatterBody), routeThemeLabel);
|
|
236
|
+
const typographyConfig = routeThemeConfig.typography;
|
|
236
237
|
return resolveAnnotatedTypographyConfig(typographyConfig ?? defaultTypography, routeThemeLabel);
|
|
237
238
|
};
|
|
238
239
|
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
8
|
+
const nornaBin = path.join(repoRoot, 'bin', 'norna.mjs');
|
|
9
|
+
const tempParent = path.join(repoRoot, 'node_modules', '.cache');
|
|
10
|
+
await mkdir(tempParent, { recursive: true });
|
|
11
|
+
const tempRoot = await mkdtemp(path.join(tempParent, 'norna-client-javascript-'));
|
|
12
|
+
const siteDir = path.join(tempRoot, 'site');
|
|
13
|
+
const routeDir = path.join(siteDir, 'routes', '010-details');
|
|
14
|
+
const configPath = path.join(siteDir, 'config.md');
|
|
15
|
+
|
|
16
|
+
const runBuild = () => {
|
|
17
|
+
const result = spawnSync(process.execPath, [nornaBin, 'build'], {
|
|
18
|
+
cwd: tempRoot,
|
|
19
|
+
encoding: 'utf8',
|
|
20
|
+
env: {
|
|
21
|
+
...process.env,
|
|
22
|
+
NORNA_SITE_DIR: siteDir,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (result.status !== 0) {
|
|
27
|
+
throw new Error([
|
|
28
|
+
`norna build exited with code ${result.status}.`,
|
|
29
|
+
result.stdout.trim(),
|
|
30
|
+
result.stderr.trim(),
|
|
31
|
+
].filter(Boolean).join('\n'));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const readPage = (pathname = 'index.html') => readFile(path.join(tempRoot, 'dist', pathname), 'utf8');
|
|
36
|
+
const getScripts = (html) => html.match(/<script\b[^>]*>[\s\S]*?<\/script>/gi) ?? [];
|
|
37
|
+
const assertNoClientJavaScript = (html, label) => {
|
|
38
|
+
assert.deepEqual(getScripts(html), [], `${label} should not require client-side JavaScript.`);
|
|
39
|
+
};
|
|
40
|
+
const assertScrollBehavior = (html, behavior, label) => {
|
|
41
|
+
assert.match(
|
|
42
|
+
html,
|
|
43
|
+
new RegExp(`<html\\b[^>]*style="[^"]*scroll-behavior: ${behavior}(?:;|"|\")`),
|
|
44
|
+
`${label} should render scroll-behavior: ${behavior}.`,
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
const writeConfig = (scrollBehavior) => writeFile(configPath, `---
|
|
48
|
+
url: https://example.com/
|
|
49
|
+
${scrollBehavior ? `scrollBehavior: ${scrollBehavior}\n` : ''}---
|
|
50
|
+
`);
|
|
51
|
+
const writeSvg = (filePath, color) => writeFile(filePath, [
|
|
52
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 90">',
|
|
53
|
+
` <rect width="160" height="90" fill="${color}"/>`,
|
|
54
|
+
'</svg>',
|
|
55
|
+
'',
|
|
56
|
+
].join('\n'));
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
await mkdir(path.join(siteDir, 'public'), { recursive: true });
|
|
60
|
+
await writeConfig();
|
|
61
|
+
await writeFile(path.join(siteDir, 'theme.md'), `---
|
|
62
|
+
typography:
|
|
63
|
+
preset: text-forward
|
|
64
|
+
presentation:
|
|
65
|
+
palette: paper
|
|
66
|
+
---
|
|
67
|
+
`);
|
|
68
|
+
await writeFile(path.join(siteDir, 'sitewide-content.md'), `---
|
|
69
|
+
navigation:
|
|
70
|
+
brand: Test site
|
|
71
|
+
---
|
|
72
|
+
`);
|
|
73
|
+
await writeFile(path.join(siteDir, 'content.md'), `---
|
|
74
|
+
title: Static single page
|
|
75
|
+
description: A single page without interactive features.
|
|
76
|
+
sections:
|
|
77
|
+
intro: {}
|
|
78
|
+
more: {}
|
|
79
|
+
---
|
|
80
|
+
## Intro {#intro}
|
|
81
|
+
|
|
82
|
+
Ordinary Markdown needs no client-side JavaScript.
|
|
83
|
+
|
|
84
|
+
## More {#more}
|
|
85
|
+
|
|
86
|
+
Additional sections do not make the page interactive.
|
|
87
|
+
`);
|
|
88
|
+
|
|
89
|
+
runBuild();
|
|
90
|
+
const instantHtml = await readPage();
|
|
91
|
+
assertNoClientJavaScript(instantHtml, 'The default instant scroll mode');
|
|
92
|
+
assertScrollBehavior(instantHtml, 'auto', 'The default instant scroll mode');
|
|
93
|
+
assert.match(instantHtml, /<nav class="page-nav"/);
|
|
94
|
+
assert.match(instantHtml, /href="#intro"/);
|
|
95
|
+
assert.match(instantHtml, /href="#more"/);
|
|
96
|
+
|
|
97
|
+
await writeConfig('browser-smooth');
|
|
98
|
+
runBuild();
|
|
99
|
+
const browserSmoothHtml = await readPage();
|
|
100
|
+
assertNoClientJavaScript(browserSmoothHtml, 'The browser smooth scroll mode');
|
|
101
|
+
assertScrollBehavior(browserSmoothHtml, 'smooth', 'The browser smooth scroll mode');
|
|
102
|
+
|
|
103
|
+
await writeConfig('norna-smooth');
|
|
104
|
+
runBuild();
|
|
105
|
+
const nornaSmoothHtml = await readPage();
|
|
106
|
+
assert.equal(
|
|
107
|
+
getScripts(nornaSmoothHtml).length,
|
|
108
|
+
1,
|
|
109
|
+
'The Norna smooth scroll mode should load only its scroll implementation.',
|
|
110
|
+
);
|
|
111
|
+
assertScrollBehavior(nornaSmoothHtml, 'auto', 'The Norna smooth scroll mode');
|
|
112
|
+
assert.match(
|
|
113
|
+
getScripts(nornaSmoothHtml)[0],
|
|
114
|
+
/nornaScrollActive/,
|
|
115
|
+
'The Norna smooth scroll mode should emit the Norna scroll implementation.',
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
await writeConfig();
|
|
119
|
+
|
|
120
|
+
await mkdir(path.join(routeDir, 'images', 'details'), { recursive: true });
|
|
121
|
+
await writeSvg(path.join(routeDir, 'images', 'details', 'first.svg'), '#7b8f78');
|
|
122
|
+
await writeSvg(path.join(routeDir, 'images', 'details', 'second.svg'), '#a7664b');
|
|
123
|
+
await writeFile(path.join(siteDir, 'content.md'), `---
|
|
124
|
+
title: Static baseline
|
|
125
|
+
description: A page without interactive features.
|
|
126
|
+
sections:
|
|
127
|
+
intro: {}
|
|
128
|
+
---
|
|
129
|
+
## Intro {#intro}
|
|
130
|
+
|
|
131
|
+
Ordinary Markdown needs no client-side JavaScript.
|
|
132
|
+
`);
|
|
133
|
+
await writeFile(path.join(routeDir, 'route-content.md'), `---
|
|
134
|
+
title: Details
|
|
135
|
+
description: Static managed images.
|
|
136
|
+
sections:
|
|
137
|
+
details: {}
|
|
138
|
+
---
|
|
139
|
+
## Details {#details}
|
|
140
|
+
|
|
141
|
+
Static image stacks remain static.
|
|
142
|
+
|
|
143
|
+
\`\`\`norna-image-stack
|
|
144
|
+
- image: first.svg
|
|
145
|
+
caption: First image.
|
|
146
|
+
- image: second.svg
|
|
147
|
+
caption: Second image.
|
|
148
|
+
\`\`\`
|
|
149
|
+
|
|
150
|
+
\`\`\`norna-card-list
|
|
151
|
+
- title: Static card
|
|
152
|
+
text: Cards do not require client-side behaviour.
|
|
153
|
+
\`\`\`
|
|
154
|
+
`);
|
|
155
|
+
|
|
156
|
+
runBuild();
|
|
157
|
+
assertNoClientJavaScript(await readPage(), 'A plain homepage in a multi-page site');
|
|
158
|
+
assertNoClientJavaScript(
|
|
159
|
+
await readPage(path.join('details', 'index.html')),
|
|
160
|
+
'A page with managed image stacks and cards',
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
await writeFile(path.join(siteDir, 'content.md'), `---
|
|
164
|
+
title: Notes
|
|
165
|
+
description: A page with an enhanced sidenote.
|
|
166
|
+
sections:
|
|
167
|
+
intro: {}
|
|
168
|
+
---
|
|
169
|
+
## Intro {#intro}
|
|
170
|
+
|
|
171
|
+
This sentence has additional context.{note-ref}
|
|
172
|
+
|
|
173
|
+
{note: The note remains readable without JavaScript, while alignment is enhanced when JavaScript runs.}
|
|
174
|
+
`);
|
|
175
|
+
await writeFile(path.join(routeDir, 'route-content.md'), `---
|
|
176
|
+
title: Carousel
|
|
177
|
+
description: An interactive image carousel.
|
|
178
|
+
sections:
|
|
179
|
+
details: {}
|
|
180
|
+
---
|
|
181
|
+
## Details {#details}
|
|
182
|
+
|
|
183
|
+
\`\`\`norna-image-carousel
|
|
184
|
+
- image: first.svg
|
|
185
|
+
caption: First slide.
|
|
186
|
+
- image: second.svg
|
|
187
|
+
caption: Second slide.
|
|
188
|
+
\`\`\`
|
|
189
|
+
`);
|
|
190
|
+
|
|
191
|
+
runBuild();
|
|
192
|
+
const noteHtml = await readPage();
|
|
193
|
+
const carouselHtml = await readPage(path.join('details', 'index.html'));
|
|
194
|
+
assert.equal(getScripts(noteHtml).length, 1, 'A page with notes should load only the note enhancement.');
|
|
195
|
+
assert.match(noteHtml, /data-note-id=/);
|
|
196
|
+
assert.equal(getScripts(carouselHtml).length, 1, 'A carousel page should load only the carousel implementation.');
|
|
197
|
+
assert.match(carouselHtml, /data-carousel/);
|
|
198
|
+
assert.match(getScripts(carouselHtml)[0], /\ssrc=/, 'Carousel JavaScript should be emitted as a module asset.');
|
|
199
|
+
|
|
200
|
+
await writeFile(path.join(siteDir, 'content.md'), `---
|
|
201
|
+
title: Banner
|
|
202
|
+
description: A page with a dismissible banner.
|
|
203
|
+
sections:
|
|
204
|
+
intro: {}
|
|
205
|
+
---
|
|
206
|
+
## Intro {#intro}
|
|
207
|
+
|
|
208
|
+
The only interactive feature is the banner.
|
|
209
|
+
`);
|
|
210
|
+
await writeFile(path.join(routeDir, 'route-content.md'), `---
|
|
211
|
+
title: Details
|
|
212
|
+
description: A second plain page.
|
|
213
|
+
sections:
|
|
214
|
+
details: {}
|
|
215
|
+
---
|
|
216
|
+
## Details {#details}
|
|
217
|
+
|
|
218
|
+
Plain route content.
|
|
219
|
+
`);
|
|
220
|
+
await writeFile(path.join(siteDir, 'sitewide-content.md'), `---
|
|
221
|
+
banners:
|
|
222
|
+
- id: test-banner
|
|
223
|
+
title: Test banner
|
|
224
|
+
text: This banner can be dismissed.
|
|
225
|
+
---
|
|
226
|
+
`);
|
|
227
|
+
|
|
228
|
+
runBuild();
|
|
229
|
+
const bannerHtml = await readPage();
|
|
230
|
+
assert.equal(getScripts(bannerHtml).length, 1, 'A dismissible banner should load only its dismissal script.');
|
|
231
|
+
assert.match(getScripts(bannerHtml)[0], /norna-banner:/);
|
|
232
|
+
|
|
233
|
+
console.log('Client JavaScript boundaries test passed.');
|
|
234
|
+
} finally {
|
|
235
|
+
await rm(tempRoot, { force: true, recursive: true });
|
|
236
|
+
}
|
|
@@ -239,6 +239,109 @@ test('content:check accepts valid inline notes and ignores note syntax in code f
|
|
|
239
239
|
});
|
|
240
240
|
});
|
|
241
241
|
|
|
242
|
+
test('content:check accepts wrapped and explicit multiline inline notes', async () => {
|
|
243
|
+
await withTempProject({
|
|
244
|
+
site: `---
|
|
245
|
+
title: Multiline inline notes
|
|
246
|
+
description: Fixture
|
|
247
|
+
---
|
|
248
|
+
## Wrapped {#wrapped}
|
|
249
|
+
This paragraph has a formatter-wrapped note.{note-ref}
|
|
250
|
+
|
|
251
|
+
{note: This note was wrapped by
|
|
252
|
+
an editor before its closing brace.}
|
|
253
|
+
|
|
254
|
+
## Explicit {#explicit}
|
|
255
|
+
This paragraph has an explicit multiline note.{note-ref}
|
|
256
|
+
|
|
257
|
+
{note:
|
|
258
|
+
This note uses the explicit
|
|
259
|
+
multiline form.
|
|
260
|
+
}
|
|
261
|
+
`,
|
|
262
|
+
files: [],
|
|
263
|
+
}, async (root) => {
|
|
264
|
+
const result = runContentScript(root, ['--check']);
|
|
265
|
+
const output = getOutput(result);
|
|
266
|
+
|
|
267
|
+
assert.equal(result.status, 0, output);
|
|
268
|
+
assert.match(output, /Content check passed\./);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test('content:check reports an unclosed multiline inline note', async () => {
|
|
273
|
+
await withTempProject({
|
|
274
|
+
site: `---
|
|
275
|
+
title: Unclosed inline note
|
|
276
|
+
description: Fixture
|
|
277
|
+
---
|
|
278
|
+
## Intro {#intro}
|
|
279
|
+
This paragraph has a note reference.{note-ref}
|
|
280
|
+
|
|
281
|
+
{note: This note never closes
|
|
282
|
+
and continues to the end of the file.
|
|
283
|
+
`,
|
|
284
|
+
files: [],
|
|
285
|
+
}, async (root) => {
|
|
286
|
+
const result = runContentScript(root, ['--check']);
|
|
287
|
+
const output = getOutput(result);
|
|
288
|
+
|
|
289
|
+
assert.equal(result.status, 1, output);
|
|
290
|
+
assert.match(output, /The note starting on line \d+ is not closed\./);
|
|
291
|
+
assert.match(output, /End it with "\}" on its own line or at the end of the note text\./);
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test('content:check rejects nested note syntax before a multiline note is closed', async () => {
|
|
296
|
+
await withTempProject({
|
|
297
|
+
site: `---
|
|
298
|
+
title: Nested inline note syntax
|
|
299
|
+
description: Fixture
|
|
300
|
+
---
|
|
301
|
+
## Nested note {#nested-note}
|
|
302
|
+
This paragraph has a note reference.{note-ref}
|
|
303
|
+
|
|
304
|
+
{note: The first note is still open
|
|
305
|
+
{note: A second note starts here.}
|
|
306
|
+
|
|
307
|
+
## Nested reference {#nested-reference}
|
|
308
|
+
This paragraph has another note reference.{note-ref}
|
|
309
|
+
|
|
310
|
+
{note: This note is still open
|
|
311
|
+
and contains {note-ref} before closing.}
|
|
312
|
+
`,
|
|
313
|
+
files: [],
|
|
314
|
+
}, async (root) => {
|
|
315
|
+
const result = runContentScript(root, ['--check']);
|
|
316
|
+
const output = getOutput(result);
|
|
317
|
+
|
|
318
|
+
assert.equal(result.status, 1, output);
|
|
319
|
+
assert.match(output, /is not closed before another note starts on line \d+\./);
|
|
320
|
+
assert.match(output, /contains "\{note-ref\}" on line \d+\./);
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
test('content:check allows escaped and inline-code note syntax inside notes', async () => {
|
|
325
|
+
await withTempProject({
|
|
326
|
+
site: `---
|
|
327
|
+
title: Literal inline note syntax
|
|
328
|
+
description: Fixture
|
|
329
|
+
---
|
|
330
|
+
## Intro {#intro}
|
|
331
|
+
This paragraph has a note reference.{note-ref}
|
|
332
|
+
|
|
333
|
+
{note: Write \\{note: ... to show escaped text, or use \`{note-ref}\` as inline code.}
|
|
334
|
+
`,
|
|
335
|
+
files: [],
|
|
336
|
+
}, async (root) => {
|
|
337
|
+
const result = runContentScript(root, ['--check']);
|
|
338
|
+
const output = getOutput(result);
|
|
339
|
+
|
|
340
|
+
assert.equal(result.status, 0, output);
|
|
341
|
+
assert.match(output, /Content check passed\./);
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
|
|
242
345
|
test('content:check rejects unpaired and repeated inline notes', async () => {
|
|
243
346
|
await withTempProject({
|
|
244
347
|
site: `---
|