@janga/norna 0.7.17 → 0.7.22

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.
Files changed (533) hide show
  1. package/README.md +32 -13
  2. package/astro.config.mjs +22 -0
  3. package/bin/norna-cli.mjs +7 -1
  4. package/package.json +46 -12
  5. package/schemas/category.schema.json +20 -0
  6. package/schemas/config.schema.json +55 -4
  7. package/schemas/content-frontmatter.schema.json +5 -5
  8. package/schemas/manifest.json +4 -2
  9. package/schemas/page-theme.schema.json +192 -0
  10. package/schemas/sitewide-content.schema.json +18 -18
  11. package/schemas/theme.schema.json +364 -226
  12. package/scripts/add-site-node.mjs +251 -0
  13. package/scripts/check-config.mjs +12 -3
  14. package/scripts/deploy-site.mjs +6 -9
  15. package/scripts/generate-images.mjs +18 -29
  16. package/scripts/generate-schemas.mjs +7 -1
  17. package/scripts/init-site.mjs +35 -0
  18. package/scripts/lib/astro-command.mjs +14 -9
  19. package/scripts/lib/editor-language-service.mjs +28 -191
  20. package/scripts/lib/heading-ids.mjs +3 -1
  21. package/scripts/lib/navigation-model.mjs +23 -17
  22. package/scripts/lib/norna-markdown-blocks.mjs +64 -145
  23. package/scripts/lib/norna-markdown-render-plugin.mjs +37 -0
  24. package/scripts/lib/object.mjs +28 -0
  25. package/scripts/lib/page-markdown.mjs +282 -0
  26. package/scripts/lib/page-model.mjs +26 -7
  27. package/scripts/lib/presentation-contract.mjs +266 -0
  28. package/scripts/lib/presentation-palette-metadata.mjs +51 -0
  29. package/scripts/lib/presentation.mjs +548 -93
  30. package/scripts/lib/project-config.mjs +73 -16
  31. package/scripts/lib/schema-definitions.mjs +89 -21
  32. package/scripts/lib/schema-editor-metadata.mjs +166 -33
  33. package/scripts/lib/schema-value-definitions.mjs +32 -4
  34. package/scripts/lib/site-content.mjs +33 -223
  35. package/scripts/lib/site-conventions.mjs +1 -0
  36. package/scripts/lib/site-paths.mjs +11 -6
  37. package/scripts/lib/site-structure.mjs +189 -0
  38. package/scripts/lib/theme-config.mjs +3 -2
  39. package/scripts/lib/theme-presets.mjs +105 -101
  40. package/scripts/lib/theme-profiles.mjs +221 -0
  41. package/scripts/lib/typography.mjs +220 -35
  42. package/scripts/lib/yaml-config.mjs +46 -6
  43. package/scripts/lib/yaml-indentation.mjs +86 -0
  44. package/scripts/show-typography.mjs +3 -36
  45. package/scripts/sync-content-sections.mjs +88 -79
  46. package/src/components/DisplaySettings.astro +107 -0
  47. package/src/components/ImageCarousel.astro +34 -13
  48. package/src/components/NavigationPageTree.astro +154 -34
  49. package/src/components/PageContentsLinks.astro +40 -0
  50. package/src/components/SectionNavigationScript.astro +68 -7
  51. package/src/components/SiteBreadcrumbs.astro +24 -18
  52. package/src/components/SiteNavigation.astro +130 -46
  53. package/src/components/SitePage.astro +65 -55
  54. package/src/components/SiteSection.astro +37 -198
  55. package/src/components/SiteTreeNavigation.astro +36 -0
  56. package/src/components/TreeNavigationScript.astro +83 -0
  57. package/src/content.config.ts +2 -8
  58. package/src/layouts/BaseLayout.astro +52 -2
  59. package/src/lib/generatedImages.ts +0 -7
  60. package/src/lib/pageThemes.ts +11 -9
  61. package/src/lib/readerPreferencesScript.mjs +141 -0
  62. package/src/lib/sectionContent.ts +120 -206
  63. package/src/lib/siteNavigation.ts +38 -19
  64. package/src/lib/sitePages.ts +115 -33
  65. package/src/pages/[...slug].astro +2 -2
  66. package/src/pages/index.astro +2 -1
  67. package/src/styles/global.css +1110 -279
  68. package/starters/basic/README.md +8 -8
  69. package/starters/basic/site/theme.yaml +1 -105
  70. package/docs/README.md +0 -135
  71. package/docs/assets/norna-dog-shelter.jpg +0 -0
  72. package/docs/commands.md +0 -189
  73. package/docs/configuration.md +0 -119
  74. package/docs/content.md +0 -342
  75. package/docs/design/command-organization.md +0 -414
  76. package/docs/design/navigation-and-theme-plan.md +0 -115
  77. package/docs/design/norna-diagram-design.md +0 -159
  78. package/docs/design/site-examples-structure.md +0 -115
  79. package/docs/engine-development.md +0 -218
  80. package/docs/getting-started.md +0 -206
  81. package/docs/how-to/embedded-site.md +0 -35
  82. package/docs/images-and-metadata.md +0 -186
  83. package/docs/local-development.md +0 -82
  84. package/docs/pages.md +0 -134
  85. package/docs/public-files.md +0 -118
  86. package/docs/publishing.md +0 -117
  87. package/docs/requirements.md +0 -54
  88. package/docs/site-files.md +0 -145
  89. package/docs/sitewide-content.md +0 -73
  90. package/docs/theme.md +0 -271
  91. package/docs/typography.md +0 -180
  92. package/examples/README.md +0 -43
  93. package/examples/complete-sites/dog-shelter-multi-page/.astro/collections/site.schema.json +0 -35
  94. package/examples/complete-sites/dog-shelter-multi-page/.astro/collections/sitewide.schema.json +0 -97
  95. package/examples/complete-sites/dog-shelter-multi-page/.astro/collections/theme.schema.json +0 -852
  96. package/examples/complete-sites/dog-shelter-multi-page/.astro/content-assets.mjs +0 -4
  97. package/examples/complete-sites/dog-shelter-multi-page/.astro/content-modules.mjs +0 -1
  98. package/examples/complete-sites/dog-shelter-multi-page/.astro/content.d.ts +0 -183
  99. package/examples/complete-sites/dog-shelter-multi-page/.astro/data-store.json +0 -1
  100. package/examples/complete-sites/dog-shelter-multi-page/.astro/dev-local.json +0 -8
  101. package/examples/complete-sites/dog-shelter-multi-page/.astro/dev.json +0 -13
  102. package/examples/complete-sites/dog-shelter-multi-page/.astro/dev.log +0 -36
  103. package/examples/complete-sites/dog-shelter-multi-page/.astro/settings.json +0 -5
  104. package/examples/complete-sites/dog-shelter-multi-page/.astro/types.d.ts +0 -2
  105. package/examples/complete-sites/dog-shelter-multi-page/README.md +0 -24
  106. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/_metadata.json +0 -74
  107. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro-B3JHJyiv.js +0 -434
  108. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro-B3JHJyiv.js.map +0 -1
  109. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_aria-query.js +0 -6390
  110. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -1
  111. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_axobject-query.js +0 -2702
  112. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -1
  113. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_html-escaper.js +0 -65
  114. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -1
  115. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -455
  116. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -1
  117. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/audit-C3SVr7dT.js +0 -1534
  118. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/audit-C3SVr7dT.js.map +0 -1
  119. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/highlight-BLtvqtzO.js +0 -48
  120. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +0 -1
  121. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/icons-C92i61-2.js +0 -42
  122. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/icons-C92i61-2.js.map +0 -1
  123. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/package.json +0 -3
  124. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -4
  125. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/settings-v5GgKks_.js +0 -190
  126. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/settings-v5GgKks_.js.map +0 -1
  127. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/toolbar-BFvJVp26.js +0 -458
  128. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +0 -1
  129. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js +0 -1016
  130. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +0 -1
  131. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/window-vo3A6TMn.js +0 -32
  132. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/window-vo3A6TMn.js.map +0 -1
  133. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/xray-DwhzGckb.js +0 -111
  134. package/examples/complete-sites/dog-shelter-multi-page/node_modules/.vite/deps/xray-DwhzGckb.js.map +0 -1
  135. package/examples/complete-sites/dog-shelter-multi-page/site/.norna/generated-images.json +0 -98
  136. package/examples/complete-sites/dog-shelter-multi-page/site/config.yaml +0 -1
  137. package/examples/complete-sites/dog-shelter-multi-page/site/content.md +0 -23
  138. package/examples/complete-sites/dog-shelter-multi-page/site/images/shelter-dog.jpg +0 -0
  139. package/examples/complete-sites/dog-shelter-multi-page/site/pages/010-dogs/content.md +0 -21
  140. package/examples/complete-sites/dog-shelter-multi-page/site/pages/010-dogs/images/rex.jpg +0 -0
  141. package/examples/complete-sites/dog-shelter-multi-page/site/pages/010-dogs/images/rover.jpg +0 -0
  142. package/examples/complete-sites/dog-shelter-multi-page/site/pages/020-adopt/content.md +0 -22
  143. package/examples/complete-sites/dog-shelter-multi-page/site/pages/020-adopt/images/adoption-dog.jpg +0 -0
  144. package/examples/complete-sites/dog-shelter-multi-page/site/public/favicon.svg +0 -10
  145. package/examples/complete-sites/dog-shelter-multi-page/site/public/logo.svg +0 -9
  146. package/examples/complete-sites/dog-shelter-multi-page/site/public/robots.txt +0 -2
  147. package/examples/complete-sites/dog-shelter-multi-page/site/sitewide-content.yaml +0 -4
  148. package/examples/complete-sites/dog-shelter-multi-page/site/theme.yaml +0 -1
  149. package/examples/complete-sites/dog-shelter-single-page/.astro/collections/site.schema.json +0 -35
  150. package/examples/complete-sites/dog-shelter-single-page/.astro/collections/sitewide.schema.json +0 -97
  151. package/examples/complete-sites/dog-shelter-single-page/.astro/collections/theme.schema.json +0 -852
  152. package/examples/complete-sites/dog-shelter-single-page/.astro/content-assets.mjs +0 -4
  153. package/examples/complete-sites/dog-shelter-single-page/.astro/content-modules.mjs +0 -1
  154. package/examples/complete-sites/dog-shelter-single-page/.astro/content.d.ts +0 -183
  155. package/examples/complete-sites/dog-shelter-single-page/.astro/data-store.json +0 -1
  156. package/examples/complete-sites/dog-shelter-single-page/.astro/dev-local.json +0 -8
  157. package/examples/complete-sites/dog-shelter-single-page/.astro/dev.json +0 -13
  158. package/examples/complete-sites/dog-shelter-single-page/.astro/dev.log +0 -18
  159. package/examples/complete-sites/dog-shelter-single-page/.astro/settings.json +0 -5
  160. package/examples/complete-sites/dog-shelter-single-page/.astro/types.d.ts +0 -2
  161. package/examples/complete-sites/dog-shelter-single-page/README.md +0 -24
  162. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/_metadata.json +0 -74
  163. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro-B3JHJyiv.js +0 -434
  164. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro-B3JHJyiv.js.map +0 -1
  165. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_aria-query.js +0 -6390
  166. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -1
  167. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_axobject-query.js +0 -2702
  168. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -1
  169. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_html-escaper.js +0 -65
  170. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -1
  171. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -455
  172. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -1
  173. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/audit-C3SVr7dT.js +0 -1534
  174. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/audit-C3SVr7dT.js.map +0 -1
  175. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/highlight-BLtvqtzO.js +0 -48
  176. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +0 -1
  177. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/icons-C92i61-2.js +0 -42
  178. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/icons-C92i61-2.js.map +0 -1
  179. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/package.json +0 -3
  180. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -4
  181. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/settings-v5GgKks_.js +0 -190
  182. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/settings-v5GgKks_.js.map +0 -1
  183. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/toolbar-BFvJVp26.js +0 -458
  184. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +0 -1
  185. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js +0 -1016
  186. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +0 -1
  187. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/window-vo3A6TMn.js +0 -32
  188. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/window-vo3A6TMn.js.map +0 -1
  189. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/xray-DwhzGckb.js +0 -111
  190. package/examples/complete-sites/dog-shelter-single-page/node_modules/.vite/deps/xray-DwhzGckb.js.map +0 -1
  191. package/examples/complete-sites/dog-shelter-single-page/site/.norna/generated-images.json +0 -50
  192. package/examples/complete-sites/dog-shelter-single-page/site/config.yaml +0 -1
  193. package/examples/complete-sites/dog-shelter-single-page/site/content.md +0 -37
  194. package/examples/complete-sites/dog-shelter-single-page/site/images/foster-dog.jpg +0 -0
  195. package/examples/complete-sites/dog-shelter-single-page/site/images/rescue-dog.jpg +0 -0
  196. package/examples/complete-sites/dog-shelter-single-page/site/public/favicon.svg +0 -10
  197. package/examples/complete-sites/dog-shelter-single-page/site/public/logo.svg +0 -9
  198. package/examples/complete-sites/dog-shelter-single-page/site/public/robots.txt +0 -2
  199. package/examples/complete-sites/dog-shelter-single-page/site/sitewide-content.yaml +0 -4
  200. package/examples/complete-sites/dog-shelter-single-page/site/theme.yaml +0 -1
  201. package/examples/feature-demos/media-and-surfaces/.astro/collections/site.schema.json +0 -35
  202. package/examples/feature-demos/media-and-surfaces/.astro/collections/sitewide.schema.json +0 -97
  203. package/examples/feature-demos/media-and-surfaces/.astro/collections/theme.schema.json +0 -852
  204. package/examples/feature-demos/media-and-surfaces/.astro/content-assets.mjs +0 -4
  205. package/examples/feature-demos/media-and-surfaces/.astro/content-modules.mjs +0 -1
  206. package/examples/feature-demos/media-and-surfaces/.astro/content.d.ts +0 -183
  207. package/examples/feature-demos/media-and-surfaces/.astro/data-store.json +0 -1
  208. package/examples/feature-demos/media-and-surfaces/.astro/dev.log +0 -14
  209. package/examples/feature-demos/media-and-surfaces/.astro/settings.json +0 -5
  210. package/examples/feature-demos/media-and-surfaces/.astro/types.d.ts +0 -2
  211. package/examples/feature-demos/media-and-surfaces/README.md +0 -21
  212. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/_metadata.json +0 -80
  213. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro-B3JHJyiv.js +0 -434
  214. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro-B3JHJyiv.js.map +0 -1
  215. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_aria-query.js +0 -6390
  216. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -1
  217. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_axobject-query.js +0 -2702
  218. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -1
  219. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_html-escaper.js +0 -65
  220. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -1
  221. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -455
  222. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -1
  223. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/audit-C3SVr7dT.js +0 -1534
  224. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/audit-C3SVr7dT.js.map +0 -1
  225. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/embla-carousel.js +0 -1389
  226. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/embla-carousel.js.map +0 -1
  227. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/highlight-BLtvqtzO.js +0 -48
  228. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +0 -1
  229. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/icons-C92i61-2.js +0 -42
  230. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/icons-C92i61-2.js.map +0 -1
  231. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/package.json +0 -3
  232. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -4
  233. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/settings-v5GgKks_.js +0 -190
  234. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/settings-v5GgKks_.js.map +0 -1
  235. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/toolbar-BFvJVp26.js +0 -458
  236. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +0 -1
  237. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/ui-library-Cd35oAvo.js +0 -1016
  238. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +0 -1
  239. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/window-vo3A6TMn.js +0 -32
  240. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/window-vo3A6TMn.js.map +0 -1
  241. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/xray-DwhzGckb.js +0 -111
  242. package/examples/feature-demos/media-and-surfaces/node_modules/.vite/deps/xray-DwhzGckb.js.map +0 -1
  243. package/examples/feature-demos/media-and-surfaces/site/.norna/generated-images.json +0 -66
  244. package/examples/feature-demos/media-and-surfaces/site/config.yaml +0 -1
  245. package/examples/feature-demos/media-and-surfaces/site/content.md +0 -15
  246. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/content.md +0 -71
  247. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/card-carousel.svg +0 -11
  248. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/card-stack.svg +0 -9
  249. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/card-surfaces.svg +0 -8
  250. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/carousel-one.svg +0 -8
  251. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/carousel-three.svg +0 -13
  252. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/carousel-two.svg +0 -8
  253. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/stack-one.svg +0 -8
  254. package/examples/feature-demos/media-and-surfaces/site/pages/010-media/images/stack-two.svg +0 -9
  255. package/examples/feature-demos/media-and-surfaces/site/pages/020-surfaces/content.md +0 -41
  256. package/examples/feature-demos/media-and-surfaces/site/pages/020-surfaces/theme.yaml +0 -3
  257. package/examples/feature-demos/media-and-surfaces/site/public/robots.txt +0 -2
  258. package/examples/feature-demos/media-and-surfaces/site/sitewide-content.yaml +0 -2
  259. package/examples/feature-demos/media-and-surfaces/site/theme.yaml +0 -1
  260. package/examples/feature-demos/sitewide-content/.astro/collections/site.schema.json +0 -59
  261. package/examples/feature-demos/sitewide-content/.astro/collections/sitewide.schema.json +0 -138
  262. package/examples/feature-demos/sitewide-content/.astro/collections/theme.schema.json +0 -755
  263. package/examples/feature-demos/sitewide-content/.astro/content-assets.mjs +0 -1
  264. package/examples/feature-demos/sitewide-content/.astro/content-modules.mjs +0 -1
  265. package/examples/feature-demos/sitewide-content/.astro/content.d.ts +0 -183
  266. package/examples/feature-demos/sitewide-content/.astro/data-store.json +0 -1
  267. package/examples/feature-demos/sitewide-content/.astro/dev.json +0 -13
  268. package/examples/feature-demos/sitewide-content/.astro/dev.log +0 -18
  269. package/examples/feature-demos/sitewide-content/.astro/settings.json +0 -5
  270. package/examples/feature-demos/sitewide-content/.astro/types.d.ts +0 -2
  271. package/examples/feature-demos/sitewide-content/README.md +0 -26
  272. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/_metadata.json +0 -74
  273. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro-B3JHJyiv.js +0 -434
  274. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro-B3JHJyiv.js.map +0 -1
  275. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_aria-query.js +0 -6390
  276. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -1
  277. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_axobject-query.js +0 -2702
  278. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -1
  279. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_html-escaper.js +0 -65
  280. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -1
  281. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -455
  282. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -1
  283. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/audit-C3SVr7dT.js +0 -1534
  284. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/audit-C3SVr7dT.js.map +0 -1
  285. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/highlight-BLtvqtzO.js +0 -48
  286. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/highlight-BLtvqtzO.js.map +0 -1
  287. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/icons-C92i61-2.js +0 -42
  288. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/icons-C92i61-2.js.map +0 -1
  289. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/package.json +0 -3
  290. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -4
  291. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/settings-v5GgKks_.js +0 -190
  292. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/settings-v5GgKks_.js.map +0 -1
  293. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/toolbar-BFvJVp26.js +0 -458
  294. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/toolbar-BFvJVp26.js.map +0 -1
  295. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/ui-library-Cd35oAvo.js +0 -1016
  296. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/ui-library-Cd35oAvo.js.map +0 -1
  297. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/window-vo3A6TMn.js +0 -32
  298. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/window-vo3A6TMn.js.map +0 -1
  299. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/xray-DwhzGckb.js +0 -111
  300. package/examples/feature-demos/sitewide-content/node_modules/.vite/deps/xray-DwhzGckb.js.map +0 -1
  301. package/examples/feature-demos/sitewide-content/site/.norna/generated-images.json +0 -1
  302. package/examples/feature-demos/sitewide-content/site/config.yaml +0 -1
  303. package/examples/feature-demos/sitewide-content/site/content.md +0 -17
  304. package/examples/feature-demos/sitewide-content/site/pages/010-logo-and-navigation/content.md +0 -17
  305. package/examples/feature-demos/sitewide-content/site/pages/020-notices/content.md +0 -23
  306. package/examples/feature-demos/sitewide-content/site/pages/030-footer/content.md +0 -18
  307. package/examples/feature-demos/sitewide-content/site/public/logo.svg +0 -6
  308. package/examples/feature-demos/sitewide-content/site/public/robots.txt +0 -2
  309. package/examples/feature-demos/sitewide-content/site/sitewide-content.yaml +0 -14
  310. package/examples/feature-demos/sitewide-content/site/theme.yaml +0 -1
  311. package/examples/feature-demos/theme-presets/.astro/collections/routeTheme.schema.json +0 -746
  312. package/examples/feature-demos/theme-presets/.astro/collections/site.schema.json +0 -59
  313. package/examples/feature-demos/theme-presets/.astro/collections/sitewide.schema.json +0 -138
  314. package/examples/feature-demos/theme-presets/.astro/collections/theme.schema.json +0 -755
  315. package/examples/feature-demos/theme-presets/.astro/content-assets.mjs +0 -4
  316. package/examples/feature-demos/theme-presets/.astro/content-modules.mjs +0 -1
  317. package/examples/feature-demos/theme-presets/.astro/content.d.ts +0 -183
  318. package/examples/feature-demos/theme-presets/.astro/data-store.json +0 -1
  319. package/examples/feature-demos/theme-presets/.astro/dev-local.json +0 -8
  320. package/examples/feature-demos/theme-presets/.astro/dev.json +0 -15
  321. package/examples/feature-demos/theme-presets/.astro/dev.log +0 -164
  322. package/examples/feature-demos/theme-presets/.astro/settings.json +0 -5
  323. package/examples/feature-demos/theme-presets/.astro/types.d.ts +0 -2
  324. package/examples/feature-demos/theme-presets/README.md +0 -18
  325. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/_metadata.json +0 -80
  326. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro-D_GIpJIE.js +0 -434
  327. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro-D_GIpJIE.js.map +0 -1
  328. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_n_aria-query.js +0 -6390
  329. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -1
  330. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_n_axobject-query.js +0 -2702
  331. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -1
  332. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_n_html-escaper.js +0 -65
  333. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -1
  334. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -455
  335. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -1
  336. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/audit-DM9Hkl5B.js +0 -1534
  337. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +0 -1
  338. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/embla-carousel.js +0 -1389
  339. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/embla-carousel.js.map +0 -1
  340. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/highlight-DnZ1ULOL.js +0 -48
  341. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +0 -1
  342. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/icons-RyebKi45.js +0 -42
  343. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/icons-RyebKi45.js.map +0 -1
  344. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/package.json +0 -3
  345. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -4
  346. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/settings-DaU-gNnK.js +0 -190
  347. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/settings-DaU-gNnK.js.map +0 -1
  348. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/toolbar-63PA619H.js +0 -458
  349. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/toolbar-63PA619H.js.map +0 -1
  350. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/ui-library--bkcNSYz.js +0 -1016
  351. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +0 -1
  352. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/window-jPkpKVcy.js +0 -32
  353. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/window-jPkpKVcy.js.map +0 -1
  354. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/xray-BXCHpEJP.js +0 -111
  355. package/examples/feature-demos/theme-presets/node_modules/.vite/deps/xray-BXCHpEJP.js.map +0 -1
  356. package/examples/feature-demos/theme-presets/site/.norna/generated-images.json +0 -290
  357. package/examples/feature-demos/theme-presets/site/config.yaml +0 -1
  358. package/examples/feature-demos/theme-presets/site/content.md +0 -14
  359. package/examples/feature-demos/theme-presets/site/pages/010-portfolio/content.md +0 -31
  360. package/examples/feature-demos/theme-presets/site/pages/010-portfolio/images/puppy-portrait.jpg +0 -0
  361. package/examples/feature-demos/theme-presets/site/pages/010-portfolio/images/shepherd-portrait.jpg +0 -0
  362. package/examples/feature-demos/theme-presets/site/pages/010-portfolio/images/white-puppy.jpg +0 -0
  363. package/examples/feature-demos/theme-presets/site/pages/010-portfolio/theme.yaml +0 -1
  364. package/examples/feature-demos/theme-presets/site/pages/020-documentation/content.md +0 -30
  365. package/examples/feature-demos/theme-presets/site/pages/020-documentation/images/black-schnauzer.jpg +0 -0
  366. package/examples/feature-demos/theme-presets/site/pages/020-documentation/images/retriever-portrait.jpg +0 -0
  367. package/examples/feature-demos/theme-presets/site/pages/020-documentation/images/schnauzer-portrait.jpg +0 -0
  368. package/examples/feature-demos/theme-presets/site/pages/020-documentation/theme.yaml +0 -1
  369. package/examples/feature-demos/theme-presets/site/pages/030-project/content.md +0 -31
  370. package/examples/feature-demos/theme-presets/site/pages/030-project/images/boxer-portrait.jpg +0 -0
  371. package/examples/feature-demos/theme-presets/site/pages/030-project/images/grass-puppy.jpg +0 -0
  372. package/examples/feature-demos/theme-presets/site/pages/030-project/images/grey-street-dog.jpg +0 -0
  373. package/examples/feature-demos/theme-presets/site/pages/030-project/theme.yaml +0 -1
  374. package/examples/feature-demos/theme-presets/site/pages/040-statement/content.md +0 -31
  375. package/examples/feature-demos/theme-presets/site/pages/040-statement/images/black-pedigree.jpg +0 -0
  376. package/examples/feature-demos/theme-presets/site/pages/040-statement/images/sheepdog-grass.jpg +0 -0
  377. package/examples/feature-demos/theme-presets/site/pages/040-statement/images/sheepdog-wide.jpg +0 -0
  378. package/examples/feature-demos/theme-presets/site/pages/040-statement/theme.yaml +0 -1
  379. package/examples/feature-demos/theme-presets/site/public/robots.txt +0 -2
  380. package/examples/feature-demos/theme-presets/site/sitewide-content.yaml +0 -3
  381. package/examples/feature-demos/theme-presets/site/theme.yaml +0 -1
  382. package/fixtures/basic/site/.norna/generated-images.json +0 -1
  383. package/fixtures/basic/site/config.yaml +0 -1
  384. package/fixtures/basic/site/content.md +0 -14
  385. package/fixtures/basic/site/public/robots.txt +0 -2
  386. package/fixtures/basic/site/sitewide-content.yaml +0 -3
  387. package/fixtures/basic/site/theme.yaml +0 -8
  388. package/fixtures/content-model-v2/.astro/collections/site.schema.json +0 -776
  389. package/fixtures/content-model-v2/.astro/collections/theme.schema.json +0 -668
  390. package/fixtures/content-model-v2/.astro/content-assets.mjs +0 -4
  391. package/fixtures/content-model-v2/.astro/content-modules.mjs +0 -1
  392. package/fixtures/content-model-v2/.astro/content.d.ts +0 -175
  393. package/fixtures/content-model-v2/.astro/data-store.json +0 -1
  394. package/fixtures/content-model-v2/.astro/dev-local.json +0 -8
  395. package/fixtures/content-model-v2/.astro/dev.json +0 -13
  396. package/fixtures/content-model-v2/.astro/dev.log +0 -231
  397. package/fixtures/content-model-v2/.astro/settings.json +0 -5
  398. package/fixtures/content-model-v2/.astro/types.d.ts +0 -2
  399. package/fixtures/content-model-v2/dist/_astro/GalleryGrid.astro_astro_type_script_index_0_lang.B0kxDyGz.js +0 -1
  400. package/fixtures/content-model-v2/dist/_astro/SitePage.BbfZub4g.css +0 -1
  401. package/fixtures/content-model-v2/dist/guide/index.html +0 -3
  402. package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-480.webp +0 -0
  403. package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-768.webp +0 -0
  404. package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-971.webp +0 -0
  405. package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-480.webp +0 -0
  406. package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-768.webp +0 -0
  407. package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-971.webp +0 -0
  408. package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-480.webp +0 -0
  409. package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-768.webp +0 -0
  410. package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-971.webp +0 -0
  411. package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1080.webp +0 -0
  412. package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1440.webp +0 -0
  413. package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1600.webp +0 -0
  414. package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-480.webp +0 -0
  415. package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-768.webp +0 -0
  416. package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-480.webp +0 -0
  417. package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-768.webp +0 -0
  418. package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-960.webp +0 -0
  419. package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1080.webp +0 -0
  420. package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1440.webp +0 -0
  421. package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1600.webp +0 -0
  422. package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-480.webp +0 -0
  423. package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-768.webp +0 -0
  424. package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1080.webp +0 -0
  425. package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1440.webp +0 -0
  426. package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1600.webp +0 -0
  427. package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-480.webp +0 -0
  428. package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-768.webp +0 -0
  429. package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1080.webp +0 -0
  430. package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1440.webp +0 -0
  431. package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1600.webp +0 -0
  432. package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-480.webp +0 -0
  433. package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-768.webp +0 -0
  434. package/fixtures/content-model-v2/dist/index.html +0 -8
  435. package/fixtures/content-model-v2/node_modules/.vite/deps/_metadata.json +0 -80
  436. package/fixtures/content-model-v2/node_modules/.vite/deps/astro-D_GIpJIE.js +0 -434
  437. package/fixtures/content-model-v2/node_modules/.vite/deps/astro-D_GIpJIE.js.map +0 -1
  438. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_aria-query.js +0 -6390
  439. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_aria-query.js.map +0 -1
  440. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_axobject-query.js +0 -2702
  441. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_axobject-query.js.map +0 -1
  442. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_html-escaper.js +0 -65
  443. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_html-escaper.js.map +0 -1
  444. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +0 -455
  445. package/fixtures/content-model-v2/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +0 -1
  446. package/fixtures/content-model-v2/node_modules/.vite/deps/audit-DM9Hkl5B.js +0 -1534
  447. package/fixtures/content-model-v2/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +0 -1
  448. package/fixtures/content-model-v2/node_modules/.vite/deps/embla-carousel.js +0 -1389
  449. package/fixtures/content-model-v2/node_modules/.vite/deps/embla-carousel.js.map +0 -1
  450. package/fixtures/content-model-v2/node_modules/.vite/deps/highlight-DnZ1ULOL.js +0 -48
  451. package/fixtures/content-model-v2/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +0 -1
  452. package/fixtures/content-model-v2/node_modules/.vite/deps/icons-RyebKi45.js +0 -42
  453. package/fixtures/content-model-v2/node_modules/.vite/deps/icons-RyebKi45.js.map +0 -1
  454. package/fixtures/content-model-v2/node_modules/.vite/deps/package.json +0 -3
  455. package/fixtures/content-model-v2/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +0 -4
  456. package/fixtures/content-model-v2/node_modules/.vite/deps/settings-DaU-gNnK.js +0 -190
  457. package/fixtures/content-model-v2/node_modules/.vite/deps/settings-DaU-gNnK.js.map +0 -1
  458. package/fixtures/content-model-v2/node_modules/.vite/deps/toolbar-63PA619H.js +0 -458
  459. package/fixtures/content-model-v2/node_modules/.vite/deps/toolbar-63PA619H.js.map +0 -1
  460. package/fixtures/content-model-v2/node_modules/.vite/deps/ui-library--bkcNSYz.js +0 -1016
  461. package/fixtures/content-model-v2/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +0 -1
  462. package/fixtures/content-model-v2/node_modules/.vite/deps/window-jPkpKVcy.js +0 -32
  463. package/fixtures/content-model-v2/node_modules/.vite/deps/window-jPkpKVcy.js.map +0 -1
  464. package/fixtures/content-model-v2/node_modules/.vite/deps/xray-BXCHpEJP.js +0 -111
  465. package/fixtures/content-model-v2/node_modules/.vite/deps/xray-BXCHpEJP.js.map +0 -1
  466. package/fixtures/content-model-v2/site/.norna/generated-images.json +0 -210
  467. package/fixtures/content-model-v2/site/config.yaml +0 -1
  468. package/fixtures/content-model-v2/site/content.md +0 -79
  469. package/fixtures/content-model-v2/site/images/adopt.svg +0 -9
  470. package/fixtures/content-model-v2/site/images/detail.jpg +0 -0
  471. package/fixtures/content-model-v2/site/images/duplicate.jpg +0 -0
  472. package/fixtures/content-model-v2/site/images/foster.svg +0 -12
  473. package/fixtures/content-model-v2/site/images/hero.jpg +0 -0
  474. package/fixtures/content-model-v2/site/images/image.jpg +0 -0
  475. package/fixtures/content-model-v2/site/images/slide-one.jpg +0 -0
  476. package/fixtures/content-model-v2/site/images/slide-three.jpg +0 -0
  477. package/fixtures/content-model-v2/site/images/slide-two.jpg +0 -0
  478. package/fixtures/content-model-v2/site/pages/010-guide/content.md +0 -18
  479. package/fixtures/content-model-v2/site/pages/010-guide/images/duplicate.jpg +0 -0
  480. package/fixtures/content-model-v2/site/theme.yaml +0 -4
  481. package/fixtures/nested-pages/site/.norna/generated-images.json +0 -10
  482. package/fixtures/nested-pages/site/config.yaml +0 -1
  483. package/fixtures/nested-pages/site/content.md +0 -15
  484. package/fixtures/nested-pages/site/pages/010-guides/content.md +0 -15
  485. package/fixtures/nested-pages/site/pages/010-guides/pages/010-installation/content.md +0 -21
  486. package/fixtures/nested-pages/site/pages/010-guides/pages/010-installation/images/diagram.svg +0 -21
  487. package/fixtures/nested-pages/site/pages/010-guides/pages/010-installation/pages/010-macos/content.md +0 -14
  488. package/fixtures/nested-pages/site/pages/010-guides/pages/020-workflows/content.md +0 -11
  489. package/fixtures/nested-pages/site/pages/010-guides/theme.yaml +0 -3
  490. package/fixtures/nested-pages/site/pages/020-reference/content.md +0 -10
  491. package/fixtures/nested-pages/site/pages/020-reference/pages/010-installation/content.md +0 -11
  492. package/fixtures/nested-pages/site/theme.yaml +0 -3
  493. package/scripts/build-pages.mjs +0 -69
  494. package/scripts/lib/example-sites.mjs +0 -37
  495. package/scripts/lib/frontmatter-yaml.mjs +0 -113
  496. package/scripts/lib/git-status.mjs +0 -7
  497. package/scripts/release.mjs +0 -153
  498. package/scripts/test-banner-visibility.mjs +0 -80
  499. package/scripts/test-ci-lockfile.mjs +0 -65
  500. package/scripts/test-cli-discovery.mjs +0 -124
  501. package/scripts/test-client-javascript.mjs +0 -218
  502. package/scripts/test-content-check.mjs +0 -621
  503. package/scripts/test-content-model-v2.mjs +0 -1629
  504. package/scripts/test-documentation.mjs +0 -187
  505. package/scripts/test-editor-language-service.mjs +0 -302
  506. package/scripts/test-engine-commands.mjs +0 -204
  507. package/scripts/test-examples.mjs +0 -24
  508. package/scripts/test-heading-ids.mjs +0 -68
  509. package/scripts/test-navigation-model.mjs +0 -63
  510. package/scripts/test-navigation-preview.mjs +0 -108
  511. package/scripts/test-navigation.mjs +0 -148
  512. package/scripts/test-nested-pages.mjs +0 -110
  513. package/scripts/test-package-check.mjs +0 -531
  514. package/scripts/test-page-model.mjs +0 -80
  515. package/scripts/test-project-config.mjs +0 -144
  516. package/scripts/test-schemas.mjs +0 -154
  517. package/scripts/test-site-public.mjs +0 -85
  518. package/scripts/test-theme-presets.mjs +0 -182
  519. package/src/components/SiteNotesScript.astro +0 -43
  520. package/starters/basic/site/images/.gitkeep +0 -1
  521. package/starters/project/.github/workflows/deploy.yml +0 -64
  522. package/starters/project/README.md +0 -84
  523. package/starters/project/package-lock.json +0 -4296
  524. package/starters/project/package.json +0 -37
  525. package/starters/project/site/config.yaml +0 -1
  526. package/starters/project/site/content.md +0 -119
  527. package/starters/project/site/pages/010-guide/content.md +0 -80
  528. package/starters/project/site/public/robots.txt +0 -2
  529. package/starters/project/site/sitewide-content.yaml +0 -3
  530. package/starters/project/site/theme.yaml +0 -31
  531. package/tsconfig.json +0 -5
  532. /package/starters/basic/site/{content.md → pages/000-home/content.md} +0 -0
  533. /package/{fixtures/basic/site → starters/basic/site/pages/000-home}/images/.gitkeep +0 -0
@@ -1,4 +1,5 @@
1
1
  import { documentationLink } from './documentation-links.mjs';
2
+ import { presentationPaletteNames } from './presentation-palette-metadata.mjs';
2
3
  import { getSchemaValueDefinition } from './schema-value-definitions.mjs';
3
4
 
4
5
  const yamlExample = (source) => `\`\`\`yaml\n${source}\n\`\`\``;
@@ -121,7 +122,7 @@ const addSitewideLogoHelp = (jsonSchema) => {
121
122
 
122
123
  logo.markdownDescription = [
123
124
  yamlExample('logo:\n height: 2rem'),
124
- '`logo` optionally overrides the displayed height of the convention-based logo file. The logo links home, and its alternative text comes from the homepage Markdown H1. This setting does not enable or select the file.',
125
+ '`logo` optionally overrides the displayed height of the convention-based logo file. Without an override, Norna uses 2.6rem on wider screens and caps the logo at 2.15rem on narrow screens. The logo links home, and its alternative text comes from the homepage Markdown H1. This setting does not enable or select the file.',
125
126
  documentationLink('Navigation logo filenames and placement', 'public-files.md', 'navigation-logo'),
126
127
  ].join('\n\n');
127
128
  logo.properties.height.examples = ['2rem'];
@@ -151,6 +152,27 @@ const addConfigHelp = (jsonSchema) => {
151
152
  'Sets the page language and selects Norna\'s built-in English or Swedish interface text. The default is `en`.',
152
153
  documentationLink('Language reference', 'configuration.md', 'language'),
153
154
  ], ['en', 'sv', 'en-GB', 'sv-SE']);
155
+ addHelp(jsonSchema, 'navigation', [
156
+ yamlExample('navigation:\n mode: automatic'),
157
+ 'Sets one navigation model for the complete site. `automatic` selects from the page hierarchy.',
158
+ documentationLink('Navigation reference', 'pages.md', 'navigation'),
159
+ ]);
160
+ addFieldHelp(
161
+ jsonSchema,
162
+ 'navigation.mode',
163
+ 'navigation:\n mode: automatic',
164
+ 'pages.md',
165
+ 'navigation',
166
+ ['automatic', 'sections', 'top', 'tree'],
167
+ );
168
+ addFieldHelp(
169
+ jsonSchema,
170
+ 'navigation.sectionTracking',
171
+ 'navigation:\n sectionTracking: true',
172
+ 'configuration.md',
173
+ 'navigationsectiontracking',
174
+ [true, false],
175
+ );
154
176
  addHelp(jsonSchema, 'scrollBehavior', [
155
177
  yamlExample('scrollBehavior: smooth'),
156
178
  'Controls same-page anchor movement. `instant` is the default; `smooth` uses the browser\'s native smooth scrolling.',
@@ -166,25 +188,17 @@ const addThemeHelp = (jsonSchema) => {
166
188
  ].join('\n\n');
167
189
  addHelp(jsonSchema, 'preset', [
168
190
  yamlExample('preset: documentation'),
169
- 'Selects coordinated navigation, layout, image sizing, typography, palette and section surfaces. This is the normal starting point for a theme.',
191
+ 'Selects coordinated corners, layout, image sizing, content-block defaults, typography, palette and section backgrounds. This is the normal starting point for a theme.',
170
192
  documentationLink('Compare theme presets', 'theme.md', 'theme-presets'),
171
193
  ]);
172
- addHelp(jsonSchema, 'navigation', [
173
- yamlExample('navigation:\n mode: automatic'),
174
- 'Sets the site-wide navigation model. Only the root theme may override this preset value.',
175
- documentationLink('Theme reference', 'theme.md'),
176
- ]);
177
- addFieldHelp(
178
- jsonSchema,
179
- 'navigation.mode',
180
- 'navigation:\n mode: automatic',
181
- 'theme.md',
182
- undefined,
183
- ['automatic', 'sections', 'top', 'tree'],
184
- );
194
+ addHelp(jsonSchema, 'corners', [
195
+ yamlExample('corners: rounded'),
196
+ 'Chooses one consistent corner treatment for navigation, cards and framed content throughout the site.',
197
+ documentationLink('Corner reference', 'theme.md', 'corners'),
198
+ ], ['square', 'rounded']);
185
199
  addHelp(jsonSchema, 'layout', [
186
- yamlExample('layout:\n density: compact\n pageWidth: 72rem'),
187
- 'Overrides page width, gutters and structural spacing after the selected preset.',
200
+ yamlExample('layout:\n contentSpacing: compact\n textWidth: narrow'),
201
+ 'Overrides text width, content spacing, page width and gutters after the selected preset.',
188
202
  documentationLink('Layout reference', 'theme.md', 'layout'),
189
203
  ]);
190
204
  addHelp(jsonSchema, 'images', [
@@ -192,24 +206,92 @@ const addThemeHelp = (jsonSchema) => {
192
206
  'Overrides the available width and height used by Norna-managed images.',
193
207
  documentationLink('Image sizing reference', 'theme.md', 'image-sizing'),
194
208
  ]);
209
+ addHelp(jsonSchema, 'blocks', [
210
+ yamlExample('blocks:\n cardList:\n width: text'),
211
+ 'Overrides preset defaults for structured Norna content blocks throughout the site. Options written directly in a Markdown block take priority.',
212
+ documentationLink('Content block defaults', 'theme.md', 'content-block-defaults'),
213
+ ]);
214
+ addHelp(jsonSchema, 'blocks.cardList', [
215
+ yamlExample('blocks:\n cardList:\n width: text'),
216
+ 'Sets site-wide defaults for card lists. A `width` option in an individual `norna-card-list` block overrides this setting.',
217
+ documentationLink('Content block defaults', 'theme.md', 'content-block-defaults'),
218
+ ]);
219
+ addFieldHelp(
220
+ jsonSchema,
221
+ 'blocks.cardList.width',
222
+ 'blocks:\n cardList:\n width: text',
223
+ 'theme.md',
224
+ 'content-block-defaults',
225
+ ['text', 'narrow', 'normal', 'wide'],
226
+ );
227
+ addSnippets(jsonSchema, 'blocks', [schemaSnippet({
228
+ label: 'Override content-block defaults',
229
+ body: {
230
+ cardList: {
231
+ width: '${1:text}',
232
+ },
233
+ },
234
+ description: 'Override a preset default for structured content blocks across the site.',
235
+ file: 'theme.md',
236
+ anchor: 'content-block-defaults',
237
+ })]);
195
238
  addHelp(jsonSchema, 'typography', [
196
239
  yamlExample('typography:\n profile: reading\n rhythm: normal'),
197
240
  'Overrides the preset\'s font stack, typography profile, rhythm or individual text settings.',
198
241
  documentationLink('Typography configuration reference', 'typography.md', 'configuration-shape'),
199
242
  ]);
200
243
  addHelp(jsonSchema, 'palette', [
201
- yamlExample('palette: paper'),
202
- 'Chooses a coordinated color system for the page frame, navigation, footer and section surfaces.',
203
- documentationLink('Palette and section surfaces', 'theme.md', 'palette-and-section-surfaces'),
204
- ], ['dark', 'light', 'paper']);
205
- addHelp(jsonSchema, 'sectionSurfaces', [
206
- yamlExample('sectionSurfaces: [base, soft, emphasis]'),
207
- 'Lists one to three semantic surfaces. Norna cycles through them in section order; omit this field to keep the preset sequence.',
208
- documentationLink('Palette and section surfaces', 'theme.md', 'palette-and-section-surfaces'),
209
- ], [['base'], ['base', 'soft'], ['base', 'soft', 'emphasis']]);
244
+ yamlExample('palette: warm-paper'),
245
+ 'Chooses the site color character. Every palette provides coordinated light and dark variants.',
246
+ documentationLink('Palette and color mode', 'theme.md', 'palette-and-color-mode'),
247
+ ], presentationPaletteNames);
248
+ addHelp(jsonSchema, 'colorMode', [
249
+ yamlExample('colorMode:\n default: system'),
250
+ 'Controls the initial light or dark appearance. Enable the reader-facing choice under readerControls.',
251
+ documentationLink('Color mode', 'theme.md', 'color-mode'),
252
+ ]);
253
+ addFieldHelp(jsonSchema, 'colorMode.default', 'colorMode:\n default: system', 'theme.md', 'color-mode', ['system', 'light', 'dark']);
254
+ addSnippets(jsonSchema, 'colorMode', [schemaSnippet({
255
+ label: 'Set the initial color mode',
256
+ body: 'colorMode:\n default: ${1:system}',
257
+ description: 'Follow the system color preference or choose a fixed initial appearance.',
258
+ file: 'theme.md',
259
+ anchor: 'color-mode',
260
+ })]);
261
+ addHelp(jsonSchema, 'readerControls', [
262
+ yamlExample('readerControls:\n colorMode: true\n focusReading: true'),
263
+ 'Adds optional color-mode and focus-reading choices to the site-wide Display panel. Reading width is always available, and tree navigation always provides Focus reading.',
264
+ documentationLink('Reader Display controls', 'theme.md', 'reader-display-controls'),
265
+ ]);
266
+ for (const [propertyPath, example] of [
267
+ ['readerControls.colorMode', 'readerControls:\n colorMode: true'],
268
+ ['readerControls.focusReading', 'readerControls:\n focusReading: true'],
269
+ ]) {
270
+ addFieldHelp(
271
+ jsonSchema,
272
+ propertyPath,
273
+ example,
274
+ 'theme.md',
275
+ 'reader-display-controls',
276
+ );
277
+ }
278
+ addSnippets(jsonSchema, 'readerControls', [schemaSnippet({
279
+ label: 'Configure the Display panel',
280
+ body: 'readerControls:\n colorMode: ${1:true}\n focusReading: ${2:true}',
281
+ description: 'Offer optional color-mode and focus-reading choices alongside the universal reading-width control. Tree navigation always provides Focus reading.',
282
+ file: 'theme.md',
283
+ anchor: 'reader-display-controls',
284
+ })]);
285
+ addHelp(jsonSchema, 'sections', [
286
+ yamlExample('sections:\n backgroundPattern: alternating'),
287
+ 'Chooses whether H2 section backgrounds stay uniform, alternate between two backgrounds or move from base to soft to emphasis and back through soft. Non-uniform patterns are available with sections and top navigation; tree navigation requires uniform.',
288
+ documentationLink('Section backgrounds', 'theme.md', 'section-backgrounds'),
289
+ ]);
290
+ addFieldHelp(jsonSchema, 'sections.backgroundPattern', 'sections:\n backgroundPattern: alternating', 'theme.md', 'section-backgrounds', ['uniform', 'alternating', 'accented']);
210
291
 
211
292
  const layoutFields = [
212
- ['layout.density', 'layout:\n density: compact'],
293
+ ['layout.contentSpacing', 'layout:\n contentSpacing: compact'],
294
+ ['layout.textWidth', 'layout:\n textWidth: narrow'],
213
295
  ['layout.pageWidth', 'layout:\n pageWidth: 72rem'],
214
296
  ['layout.gutter', 'layout:\n gutter:\n desktop: clamp(1.25rem, 4vw, 3rem)\n mobile: 1rem'],
215
297
  ['layout.gutter.desktop', 'layout:\n gutter:\n desktop: clamp(1.25rem, 4vw, 3rem)'],
@@ -301,9 +383,9 @@ const addThemeHelp = (jsonSchema) => {
301
383
  ['typography.fontFamily', 'typography:\n fontFamily: "Arial, sans-serif"'],
302
384
  ['typography.profile', 'typography:\n profile: reading'],
303
385
  ['typography.rhythm', 'typography:\n rhythm: normal'],
304
- ['typography.overrides', 'typography:\n overrides:\n body:\n width: narrow'],
386
+ ['typography.overrides', 'typography:\n overrides:\n body:\n lineHeight: 1.55'],
305
387
  ['typography.overrides.headings', 'typography:\n overrides:\n headings:\n h2:\n size: medium'],
306
- ['typography.overrides.body', 'typography:\n overrides:\n body:\n width: narrow'],
388
+ ['typography.overrides.body', 'typography:\n overrides:\n body:\n lineHeight: 1.55'],
307
389
  ['typography.overrides.caption', 'typography:\n overrides:\n caption:\n size: small'],
308
390
  ];
309
391
  for (const [propertyPath, example] of typographyFields) {
@@ -346,7 +428,6 @@ const addThemeHelp = (jsonSchema) => {
346
428
  textOverrideHelp(propertyPath, `${prefix}\n `, true);
347
429
  }
348
430
  textOverrideHelp('typography.overrides.body', 'typography:\n overrides:\n body:');
349
- addFieldHelp(jsonSchema, 'typography.overrides.body.width', 'typography:\n overrides:\n body:\n width: narrow', 'typography.md', 'configuration-shape');
350
431
  addFieldHelp(jsonSchema, 'typography.overrides.body.paragraphSpacing', 'typography:\n overrides:\n body:\n paragraphSpacing: 1em', 'typography.md', 'configuration-shape');
351
432
  textOverrideHelp('typography.overrides.caption', 'typography:\n overrides:\n caption:');
352
433
  addFieldHelp(jsonSchema, 'typography.overrides.caption.spacingBefore', 'typography:\n overrides:\n caption:\n spacingBefore: 0.5em', 'typography.md', 'configuration-shape');
@@ -359,9 +440,8 @@ const addThemeHelp = (jsonSchema) => {
359
440
  weight: '${2:600}',
360
441
  },
361
442
  },
362
- body: {
363
- width: '${3:narrow}',
364
- lineHeight: '${4:1.55}',
443
+ body: {
444
+ lineHeight: '${3:1.55}',
365
445
  },
366
446
  },
367
447
  description: 'Start a focused set of heading and body-text overrides.',
@@ -370,6 +450,44 @@ const addThemeHelp = (jsonSchema) => {
370
450
  })]);
371
451
  };
372
452
 
453
+ const addPageThemeHelp = (jsonSchema) => {
454
+ jsonSchema.markdownDescription = [
455
+ yamlExample('layout:\n textWidth: narrow\n contentSpacing: compact'),
456
+ 'A limited theme in a page or category directory may adjust only page layout, managed-image sizing and the section background pattern. Descendant pages inherit these values. Tree navigation requires a uniform section background. Site colors, corners, typography, content-block defaults and navigation stay consistent.',
457
+ documentationLink('Page theme reference', 'theme.md', 'page-themes'),
458
+ ].join('\n\n');
459
+ addHelp(jsonSchema, 'layout', [
460
+ yamlExample('layout:\n textWidth: narrow\n contentSpacing: compact'),
461
+ 'Adjusts body-text line length and vertical content spacing for pages below this directory.',
462
+ documentationLink('Page theme reference', 'theme.md', 'page-themes'),
463
+ ]);
464
+ addFieldHelp(jsonSchema, 'layout.textWidth', 'layout:\n textWidth: narrow', 'theme.md', 'page-themes', ['narrow', 'normal', 'wide']);
465
+ addFieldHelp(jsonSchema, 'layout.contentSpacing', 'layout:\n contentSpacing: compact', 'theme.md', 'page-themes', ['compact', 'normal', 'spacious']);
466
+ addHelp(jsonSchema, 'images', [
467
+ yamlExample('images:\n width: 900px'),
468
+ 'Adjusts managed-image sizing for pages below this directory.',
469
+ documentationLink('Image sizing reference', 'theme.md', 'image-sizing'),
470
+ ]);
471
+ const imageFields = [
472
+ ['images.width', 'images:\n width: 900px'],
473
+ ['images.maxAvailableWidthPercent', 'images:\n maxAvailableWidthPercent:\n desktop: 100\n mobile: 100'],
474
+ ['images.maxAvailableWidthPercent.desktop', 'images:\n maxAvailableWidthPercent:\n desktop: 100'],
475
+ ['images.maxAvailableWidthPercent.mobile', 'images:\n maxAvailableWidthPercent:\n mobile: 100'],
476
+ ['images.maxAvailableHeightPercent', 'images:\n maxAvailableHeightPercent:\n desktop: 74\n mobile: 68'],
477
+ ['images.maxAvailableHeightPercent.desktop', 'images:\n maxAvailableHeightPercent:\n desktop: 74'],
478
+ ['images.maxAvailableHeightPercent.mobile', 'images:\n maxAvailableHeightPercent:\n mobile: 68'],
479
+ ];
480
+ for (const [propertyPath, example] of imageFields) {
481
+ addFieldHelp(jsonSchema, propertyPath, example, 'theme.md', 'image-sizing');
482
+ }
483
+ addHelp(jsonSchema, 'sections', [
484
+ yamlExample('sections:\n backgroundPattern: alternating'),
485
+ 'Adjusts the H2 section background pattern for pages below this directory. Alternating and accented create full-width bands but are invalid when navigation resolves to tree.',
486
+ documentationLink('Page theme reference', 'theme.md', 'page-themes'),
487
+ ]);
488
+ addFieldHelp(jsonSchema, 'sections.backgroundPattern', 'sections:\n backgroundPattern: alternating', 'theme.md', 'page-themes', ['uniform', 'alternating', 'accented']);
489
+ };
490
+
373
491
  const addSitewideHelp = (jsonSchema) => {
374
492
  jsonSchema.markdownDescription = [
375
493
  yamlExample('footer:\n copyrightMessage: Copyright Example Owner.'),
@@ -462,13 +580,28 @@ const addContentHelp = (jsonSchema) => {
462
580
  addFieldHelp(jsonSchema, 'navigation.listed', 'navigation:\n listed: false', 'pages.md', 'navigation', [true, false]);
463
581
  };
464
582
 
583
+ const addCategoryHelp = (jsonSchema) => {
584
+ jsonSchema.markdownDescription = [
585
+ yamlExample('label: Guides'),
586
+ '`category.yaml` creates a navigation-only group for child pages. It has no page content and produces no URL of its own.',
587
+ documentationLink('Navigation category reference', 'pages.md', 'navigation-categories'),
588
+ ].join('\n\n');
589
+ addHelp(jsonSchema, 'label', [
590
+ yamlExample('label: Guides'),
591
+ 'The category label shown in global navigation, tree navigation, mobile navigation, and breadcrumbs.',
592
+ documentationLink('Navigation category reference', 'pages.md', 'navigation-categories'),
593
+ ]);
594
+ };
595
+
465
596
  export const applySchemaEditorMetadata = (filename, jsonSchema) => {
466
597
  addValueDescriptions(jsonSchema);
598
+ if (filename === 'category.schema.json') addCategoryHelp(jsonSchema);
467
599
  if (filename === 'config.schema.json') {
468
600
  addLanguageSuggestions(jsonSchema);
469
601
  addConfigHelp(jsonSchema);
470
602
  }
471
603
  if (filename === 'theme.schema.json') addThemeHelp(jsonSchema);
604
+ if (filename === 'page-theme.schema.json') addPageThemeHelp(jsonSchema);
472
605
  if (filename === 'sitewide-content.schema.json') addSitewideHelp(jsonSchema);
473
606
  if (filename === 'content-frontmatter.schema.json') addContentHelp(jsonSchema);
474
607
  return jsonSchema;
@@ -2,6 +2,10 @@ import {
2
2
  getThemePresetMetadata,
3
3
  themePresetNames,
4
4
  } from './theme-presets.mjs';
5
+ import {
6
+ getPresentationPaletteMetadata,
7
+ presentationPaletteNames,
8
+ } from './presentation-palette-metadata.mjs';
5
9
 
6
10
  const option = (title, description) => Object.freeze({ title, description });
7
11
  const definition = (values, options) => Object.freeze({
@@ -44,6 +48,12 @@ export const schemaValueDefinitions = Object.freeze([
44
48
  normal: option('Normal', 'Use the balanced default line length.'),
45
49
  wide: option('Wide', 'Allow body text to use more horizontal space.'),
46
50
  }),
51
+ definition(['text', 'narrow', 'normal', 'wide'], {
52
+ text: option('Text width', 'Match the active body-text width, including a reader-selected reading width.'),
53
+ narrow: option('Narrow', 'Limit the complete card list to at most 48rem.'),
54
+ normal: option('Normal', 'Limit the complete card list to at most 56rem.'),
55
+ wide: option('Wide', 'Allow the complete card list to use the available page-layout width.'),
56
+ }),
47
57
  definition([400, 500, 600, 700], {
48
58
  400: option('Regular', 'Use regular font weight.'),
49
59
  500: option('Medium', 'Use medium font weight.'),
@@ -56,10 +66,28 @@ export const schemaValueDefinitions = Object.freeze([
56
66
  reading: option('Reading', 'Reading-focused typography with narrower text and relaxed line height.'),
57
67
  statement: option('Statement', 'Stronger headings and tighter body rhythm for short, expressive pages.'),
58
68
  }),
59
- definition(['dark', 'light', 'paper'], {
60
- dark: option('Dark', 'Black page and section surfaces with light text.'),
61
- light: option('Light', 'White and cool light surfaces with dark text.'),
62
- paper: option('Paper', 'Warm off-white surfaces with dark text.'),
69
+ definition(presentationPaletteNames, Object.fromEntries(presentationPaletteNames.map((name) => {
70
+ const metadata = getPresentationPaletteMetadata(name);
71
+ return [name, option(metadata.title, `${metadata.description} Includes coordinated light and dark variants.`)];
72
+ }))),
73
+ definition(['system', 'light', 'dark'], {
74
+ system: option('System', 'Follow the visitor\'s operating-system light or dark preference.'),
75
+ light: option('Light', 'Start with the palette\'s light appearance.'),
76
+ dark: option('Dark', 'Start with the palette\'s dark appearance.'),
77
+ }),
78
+ definition(['square', 'rounded'], {
79
+ square: option('Square', 'Use square corners for navigation, cards and framed content.'),
80
+ rounded: option('Rounded', 'Use restrained rounded corners consistently across the site.'),
81
+ }),
82
+ definition(['uniform', 'alternating', 'accented'], {
83
+ uniform: option('Uniform', 'Use the normal page background for every H2 section. Tree navigation requires this pattern.'),
84
+ alternating: option('Alternating', 'Alternate normal and subtly contrasting full-width section backgrounds. Available with sections and top navigation.'),
85
+ accented: option('Accented', 'Move through base, soft, emphasis and soft full-width section backgrounds before repeating. Available with sections and top navigation.'),
86
+ }),
87
+ definition(['compact', 'normal', 'spacious'], {
88
+ compact: option('Compact', 'Use restrained spacing between sections and structured blocks.'),
89
+ normal: option('Normal', 'Use balanced content spacing.'),
90
+ spacious: option('Spacious', 'Use more expansive spacing between sections and structured blocks.'),
63
91
  }),
64
92
  definition(['base', 'soft', 'emphasis'], {
65
93
  base: option('Base', 'Use the palette\'s normal page surface.'),
@@ -1,19 +1,13 @@
1
- import { access, readdir, readFile } from 'node:fs/promises';
1
+ import { readdir, readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import {
4
4
  siteContentLabel,
5
- siteContentPath,
6
- siteDir,
7
- siteDirLabel,
8
- siteImagesDir,
9
- siteImagesLabel,
10
- sitePagesDir,
11
- sitePagesLabel,
12
5
  sitewideContentLabel,
13
6
  } from './site-paths.mjs';
14
- import { parsePageDirectoryPath } from './page-model.mjs';
15
- import { getMarkdownHeadings } from './heading-ids.mjs';
16
7
  import { schemaTopLevelKeys } from './schema-definitions.mjs';
8
+ import { getIndentInfo, validateYamlIndentation } from './yaml-indentation.mjs';
9
+
10
+ export { getContentFiles } from './site-structure.mjs';
17
11
 
18
12
  export const rasterImageExtensions = new Set(['.jpg', '.jpeg', '.png']);
19
13
  export const staticImageExtensions = new Set(['.svg']);
@@ -25,7 +19,7 @@ const knownConfigTopLevelFrontmatterKeys = new Set(schemaTopLevelKeys.config);
25
19
  const knownContentTopLevelFrontmatterKeys = new Set(schemaTopLevelKeys.content);
26
20
  const knownThemeTopLevelFrontmatterKeys = new Set(schemaTopLevelKeys.theme);
27
21
  const knownPageThemeTopLevelFrontmatterKeys = new Set(
28
- [...knownThemeTopLevelFrontmatterKeys].filter((key) => key !== 'navigation'),
22
+ schemaTopLevelKeys.pageTheme,
29
23
  );
30
24
  const knownSitewideTopLevelFrontmatterKeys = new Set(schemaTopLevelKeys.sitewide);
31
25
  const knownNestedFrontmatterKeys = new Set([
@@ -34,9 +28,11 @@ const knownNestedFrontmatterKeys = new Set([
34
28
  'body',
35
29
  'blockGap',
36
30
  'caption',
31
+ 'colorMode',
37
32
  'carousel',
38
- 'density',
33
+ 'contentSpacing',
39
34
  'desktop',
35
+ 'default',
40
36
  'fontFamily',
41
37
  'from',
42
38
  'finalSectionBottom',
@@ -65,13 +61,19 @@ const knownNestedFrontmatterKeys = new Set([
65
61
  'palette',
66
62
  'preset',
67
63
  'profile',
64
+ 'readerControls',
65
+ 'readingWidth',
68
66
  'rhythm',
69
67
  'sectionGap',
70
- 'sectionSurfaces',
68
+ 'backgroundPattern',
69
+ 'sections',
70
+ 'corners',
71
+ 'focusReading',
71
72
  'size',
72
73
  'spacingAfter',
73
74
  'spacingBefore',
74
75
  'theme',
76
+ 'textWidth',
75
77
  'typography',
76
78
  'until',
77
79
  'visible',
@@ -80,87 +82,6 @@ const knownNestedFrontmatterKeys = new Set([
80
82
 
81
83
  export const toPosixPath = (filePath) => filePath.split(path.sep).join('/');
82
84
 
83
- const fileExists = async (filePath) => access(filePath).then(() => true, () => false);
84
-
85
- export const getContentFiles = async () => {
86
- const legacyRoutesDir = path.join(siteDir, 'routes');
87
- const legacyRoutes = await readdir(legacyRoutesDir).catch((error) => {
88
- if (error?.code === 'ENOENT') return null;
89
- throw error;
90
- });
91
- if (legacyRoutes !== null) {
92
- throw new Error(`${siteDirLabel}/routes is no longer supported. Rename it to ${sitePagesLabel} and use NNN-page-id directory names.`);
93
- }
94
-
95
- const contentFiles = [{
96
- contentLabel: siteContentLabel,
97
- contentPath: siteContentPath,
98
- imagesDir: siteImagesDir,
99
- imagesLabel: siteImagesLabel,
100
- isHome: true,
101
- pageDirectory: null,
102
- pageDirectories: [],
103
- pageId: null,
104
- pageIds: [],
105
- pageOrder: 0,
106
- pageOrders: [],
107
- pagePath: '',
108
- parentPagePath: null,
109
- depth: 0,
110
- }];
111
- const collectPageContentFiles = async (pagesDir, pagesLabel, parentPageDirectory = '') => {
112
- const pageEntries = await readdir(pagesDir, { withFileTypes: true }).catch((error) => {
113
- if (error?.code === 'ENOENT') {
114
- return [];
115
- }
116
-
117
- throw error;
118
- });
119
-
120
- for (const entry of pageEntries.sort((left, right) => left.name.localeCompare(right.name, 'en'))) {
121
- if (!entry.isDirectory()) continue;
122
-
123
- const pageDirectory = parentPageDirectory
124
- ? `${parentPageDirectory}/pages/${entry.name}`
125
- : entry.name;
126
- const pageLabel = `${pagesLabel}/${entry.name}`;
127
- const pageDir = path.join(pagesDir, entry.name);
128
- const pageContentPath = path.join(pageDir, 'content.md');
129
-
130
- if (!(await fileExists(pageContentPath))) {
131
- const childPageEntries = await readdir(path.join(pageDir, 'pages'), { withFileTypes: true }).catch((error) => {
132
- if (error?.code === 'ENOENT') return [];
133
- throw error;
134
- });
135
- if (childPageEntries.some((childEntry) => childEntry.isDirectory())) {
136
- throw new Error(`${pageLabel} contains nested pages but has no content.md of its own.`);
137
- }
138
- continue;
139
- }
140
- const pageMetadata = parsePageDirectoryPath(pageDirectory, pageLabel);
141
-
142
- contentFiles.push({
143
- contentLabel: `${pageLabel}/content.md`,
144
- contentPath: pageContentPath,
145
- imagesDir: path.join(pageDir, 'images'),
146
- imagesLabel: `${pageLabel}/images`,
147
- isHome: false,
148
- ...pageMetadata,
149
- });
150
-
151
- await collectPageContentFiles(
152
- path.join(pageDir, 'pages'),
153
- `${pageLabel}/pages`,
154
- pageDirectory,
155
- );
156
- }
157
- };
158
-
159
- await collectPageContentFiles(sitePagesDir, sitePagesLabel);
160
-
161
- return contentFiles;
162
- };
163
-
164
85
  export const splitSiteFile = (source, label = siteContentLabel) => {
165
86
  const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
166
87
 
@@ -185,89 +106,12 @@ export const splitSiteFile = (source, label = siteContentLabel) => {
185
106
 
186
107
  export const readSiteFile = async (sitePath, label = siteContentLabel) => splitSiteFile(await readFile(sitePath, 'utf8'), label);
187
108
 
188
- const getIndentInfo = (line) => {
189
- const characters = Array.from(line);
190
- const indentCharacters = [];
191
-
192
- for (const character of characters) {
193
- if (character === ' ' || character === '\t' || character === '\u00a0' || character === '\uFFFD' || character === '\u00c2') {
194
- indentCharacters.push(character);
195
- continue;
196
- }
197
-
198
- break;
199
- }
200
-
201
- return {
202
- indent: indentCharacters.length,
203
- hasInvalidWhitespace: indentCharacters.some((character) => character !== ' '),
204
- };
205
- };
206
-
207
- const getNextFrontmatterEntry = (lines, startIndex) => {
208
- for (let index = startIndex + 1; index < lines.length; index += 1) {
209
- const line = lines[index];
210
- if (!line.trim() || line.trim().startsWith('#') || frontmatterDelimiterRegex.test(line)) {
211
- continue;
212
- }
213
-
214
- return {
215
- index,
216
- line,
217
- ...getIndentInfo(line),
218
- };
219
- }
220
-
221
- return null;
222
- };
223
-
224
109
  export const validateFrontmatterIndentation = (frontmatter, addIssue) => {
225
- const lines = frontmatter.split(/\r?\n/);
226
-
227
- for (const [index, line] of lines.entries()) {
228
- const lineNumber = index + 1;
229
- const trimmed = line.trim();
230
-
231
- if (!trimmed || trimmed.startsWith('#') || frontmatterDelimiterRegex.test(line)) {
232
- continue;
233
- }
234
-
235
- const { indent, hasInvalidWhitespace } = getIndentInfo(line);
236
-
237
- if (hasInvalidWhitespace) {
238
- addIssue({
239
- severity: 'error',
240
- message: `Frontmatter line ${lineNumber} uses tabs, non-breaking spaces, or invalid whitespace for indentation.`,
241
- fix: 'Replace the indentation on that line with ordinary spaces.',
242
- });
243
- continue;
244
- }
245
-
246
- if (indent % 2 !== 0) {
247
- addIssue({
248
- severity: 'error',
249
- message: `Frontmatter line ${lineNumber} is indented with ${indent} spaces.`,
250
- fix: 'Use 2-space indentation levels in frontmatter.',
251
- });
252
- }
253
-
254
- const keyValueMatch = line.match(/^(\s*)[A-Za-z][A-Za-z0-9-]*:\s+(.+)$/);
255
- if (!keyValueMatch) continue;
256
-
257
- const value = keyValueMatch[2].trim();
258
- if (value === '|' || value === '>' || value.startsWith('|') || value.startsWith('>')) {
259
- continue;
260
- }
261
-
262
- const nextEntry = getNextFrontmatterEntry(lines, index);
263
- if (!nextEntry || nextEntry.indent <= indent) continue;
264
-
265
- addIssue({
266
- severity: 'error',
267
- message: `Frontmatter line ${nextEntry.index + 1} is indented under line ${lineNumber}, but line ${lineNumber} already has a value.`,
268
- fix: 'Move the later line to the same indentation level as its sibling, or place it under a key that has no value.',
269
- });
270
- }
110
+ validateYamlIndentation(frontmatter, (issue) => addIssue({
111
+ ...issue,
112
+ message: issue.message.replace(/^YAML/, 'Frontmatter'),
113
+ fix: issue.fix.replace(/YAML/g, 'frontmatter'),
114
+ }));
271
115
  };
272
116
 
273
117
  export const validateFrontmatterStructure = (frontmatter, addIssue, {
@@ -303,9 +147,19 @@ export const validateFrontmatterStructure = (frontmatter, addIssue, {
303
147
  fix = 'Put local image references in norna-image-stack or norna-image-carousel blocks in the Markdown body.';
304
148
  } else if (fileKind === 'content' && knownThemeTopLevelFrontmatterKeys.has(key)) {
305
149
  fix = `Move "${key}:" to theme.yaml. Visual settings do not belong in content frontmatter.`;
306
- } else if (fileKind === 'page theme' && key === 'navigation') {
307
- message = `Frontmatter line ${lineNumber}: page themes may not define navigation.`;
308
- fix = 'Set the site-wide navigation mode under "navigation:" in the root theme.yaml.';
150
+ } else if ((fileKind === 'theme' || fileKind === 'page theme') && key === 'navigation') {
151
+ message = `Frontmatter line ${lineNumber}: navigation is technical, site-wide configuration and does not belong in ${fileKind}. Set it in config.yaml.`;
152
+ fix = 'Set the navigation mode under "navigation:" in config.yaml.';
153
+ } else if ((fileKind === 'theme' || fileKind === 'page theme') && key === 'shape') {
154
+ message = fileKind === 'page theme'
155
+ ? `Frontmatter line ${lineNumber}: "shape" was replaced by the site-wide "corners" setting, which page themes cannot override.`
156
+ : `Frontmatter line ${lineNumber}: "shape" was replaced by "corners". Use "square" or replace the old "soft" value with "rounded".`;
157
+ fix = fileKind === 'page theme'
158
+ ? 'Remove "shape:" from this page theme. Set "corners: square" or "corners: rounded" in the root theme.yaml when an override is needed.'
159
+ : 'Replace "shape:" with "corners:". Use "square" or replace the old "soft" value with "rounded".';
160
+ } else if (fileKind === 'page theme' && ['preset', 'corners', 'palette', 'typography'].includes(key)) {
161
+ message = `Frontmatter line ${lineNumber}: page themes may not define site-wide visual identity through "${key}".`;
162
+ fix = `Move "${key}:" to the root theme.yaml. Page themes may set only layout.textWidth, layout.contentSpacing, images, and sections.backgroundPattern.`;
309
163
  } else if ((fileKind === 'theme' || fileKind === 'page theme') && ['logo', 'site'].includes(key)) {
310
164
  message = `Frontmatter line ${lineNumber}: ${fileKind} may not define navigation logo settings. Optional logo display settings belong under "logo:" in ${sitewideContentLabel}.`;
311
165
  fix = `Move only the logo display settings under "logo:" in ${sitewideContentLabel}; the homepage Markdown H1 supplies navigation text and logo alternative text.`;
@@ -364,31 +218,6 @@ export const readThemeFile = async (sitePath) => {
364
218
  export const getDeprecatedInlineStyleReferences = (body) => Array.from(body.matchAll(deprecatedInlineStyleReferenceRegex))
365
219
  .map((match) => match[1]);
366
220
 
367
- export const getBodySections = async (body) => {
368
- const { headings, source } = await getMarkdownHeadings(body);
369
- const structuralHeadings = headings.filter((heading) => heading.depth <= 2);
370
- const prelude = structuralHeadings.length > 0 ? source.slice(0, structuralHeadings[0].index) : source;
371
- const sections = structuralHeadings.map((heading, index) => {
372
- const next = structuralHeadings[index + 1];
373
- const end = next?.index ?? source.length;
374
-
375
- return {
376
- ...heading,
377
- heading: heading.source,
378
- isPageTitle: heading.depth === 1,
379
- level: heading.depth,
380
- text: source.slice(heading.index, end).trimEnd(),
381
- };
382
- });
383
-
384
- return {
385
- headings,
386
- pageHeadings: sections.filter((section) => section.isPageTitle),
387
- prelude,
388
- sections,
389
- };
390
- };
391
-
392
221
  export const getImageFiles = async (directory) => {
393
222
  const entries = await readdir(directory, { withFileTypes: true }).catch((error) => {
394
223
  if (error?.code === 'ENOENT') {
@@ -412,25 +241,6 @@ export const getImageFiles = async (directory) => {
412
241
  return files;
413
242
  };
414
243
 
415
- export const getImageIndex = async (contentDir, fail, contentLabel = siteImagesLabel) => {
416
- const imageFiles = await getImageFiles(contentDir);
417
- const imagesByName = new Map();
418
-
419
- for (const imagePath of imageFiles) {
420
- const imageName = path.basename(imagePath);
421
- const existingPath = imagesByName.get(imageName);
422
-
423
- if (existingPath) {
424
- fail(`Duplicate image filename "${imageName}" found at ${contentLabel}/${toPosixPath(path.relative(contentDir, existingPath))} and ${contentLabel}/${toPosixPath(path.relative(contentDir, imagePath))}. The filename is ambiguous within this page image root.`);
425
- continue;
426
- }
427
-
428
- imagesByName.set(imageName, imagePath);
429
- }
430
-
431
- return imagesByName;
432
- };
433
-
434
244
  export const getImageCandidatesByName = async (contentDir) => {
435
245
  const imageFiles = await getImageFiles(contentDir);
436
246
  const imagesByName = new Map();