@janga/norna 0.7.13 → 0.7.15

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 (146) hide show
  1. package/README.md +15 -9
  2. package/bin/norna-cli.mjs +11 -4
  3. package/docs/README.md +71 -43
  4. package/docs/commands.md +34 -20
  5. package/docs/configuration.md +43 -62
  6. package/docs/content.md +34 -7
  7. package/docs/design/command-organization.md +15 -8
  8. package/docs/design/norna-diagram-design.md +6 -6
  9. package/docs/design/site-examples-structure.md +1 -1
  10. package/docs/engine-development.md +22 -9
  11. package/docs/getting-started.md +29 -16
  12. package/docs/how-to/embedded-site.md +1 -1
  13. package/docs/images-and-metadata.md +3 -3
  14. package/docs/local-development.md +11 -3
  15. package/docs/public-files.md +105 -0
  16. package/docs/publishing.md +4 -8
  17. package/docs/routes.md +6 -7
  18. package/docs/site-files.md +144 -0
  19. package/docs/sitewide-content.md +47 -33
  20. package/docs/theme.md +37 -49
  21. package/docs/typography.md +25 -31
  22. package/examples/complete-sites/dog-shelter-multi-page/README.md +8 -0
  23. package/examples/complete-sites/{dog-shelter-single-page/site/config.md → dog-shelter-multi-page/site/config.yaml} +0 -2
  24. package/examples/complete-sites/dog-shelter-multi-page/site/sitewide-content.yaml +6 -0
  25. package/examples/complete-sites/dog-shelter-multi-page/site/{theme.md → theme.yaml} +0 -2
  26. package/examples/complete-sites/dog-shelter-single-page/README.md +8 -0
  27. package/examples/complete-sites/{dog-shelter-multi-page/site/config.md → dog-shelter-single-page/site/config.yaml} +0 -2
  28. package/examples/complete-sites/dog-shelter-single-page/site/sitewide-content.yaml +6 -0
  29. package/examples/complete-sites/dog-shelter-single-page/site/{theme.md → theme.yaml} +0 -2
  30. package/examples/feature-demos/media-and-surfaces/.astro/data-store.json +1 -1
  31. package/examples/feature-demos/media-and-surfaces/README.md +1 -1
  32. package/examples/feature-demos/media-and-surfaces/site/{config.md → config.yaml} +0 -2
  33. package/examples/feature-demos/media-and-surfaces/site/content.md +2 -2
  34. package/examples/feature-demos/media-and-surfaces/site/routes/020-surfaces/{route-content.md → content.md} +3 -7
  35. package/examples/feature-demos/media-and-surfaces/site/routes/020-surfaces/theme.yaml +3 -0
  36. package/examples/feature-demos/media-and-surfaces/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  37. package/examples/feature-demos/media-and-surfaces/site/{theme.md → theme.yaml} +0 -2
  38. package/examples/feature-demos/sitewide-content/README.md +8 -0
  39. package/examples/feature-demos/sitewide-content/site/{config.md → config.yaml} +0 -2
  40. package/examples/feature-demos/sitewide-content/site/routes/010-identity/{route-content.md → content.md} +3 -3
  41. package/examples/feature-demos/sitewide-content/site/routes/020-notices/{route-content.md → content.md} +1 -1
  42. package/examples/feature-demos/sitewide-content/site/routes/030-footer/{route-content.md → content.md} +1 -1
  43. package/examples/feature-demos/sitewide-content/site/{sitewide-content.md → sitewide-content.yaml} +1 -11
  44. package/examples/feature-demos/sitewide-content/site/{theme.md → theme.yaml} +0 -2
  45. package/examples/feature-demos/theme-presets/site/config.yaml +1 -0
  46. package/examples/feature-demos/theme-presets/site/routes/010-portfolio/{theme.md → theme.yaml} +0 -2
  47. package/examples/feature-demos/theme-presets/site/routes/020-documentation/{theme.md → theme.yaml} +0 -2
  48. package/examples/feature-demos/theme-presets/site/routes/030-project/theme.yaml +1 -0
  49. package/examples/feature-demos/theme-presets/site/routes/040-statement/{route-content.md → content.md} +1 -1
  50. package/examples/feature-demos/theme-presets/site/routes/040-statement/{theme.md → theme.yaml} +0 -2
  51. package/examples/feature-demos/theme-presets/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  52. package/examples/feature-demos/theme-presets/site/theme.yaml +1 -0
  53. package/fixtures/basic/site/{config.md → config.yaml} +0 -2
  54. package/fixtures/basic/site/content.md +3 -3
  55. package/fixtures/basic/site/{sitewide-content.md → sitewide-content.yaml} +0 -2
  56. package/fixtures/basic/site/{theme.md → theme.yaml} +3 -6
  57. package/fixtures/content-model-v2/site/{config.md → config.yaml} +0 -2
  58. package/fixtures/content-model-v2/site/theme.yaml +4 -0
  59. package/package.json +10 -3
  60. package/schemas/config.schema.json +77 -0
  61. package/schemas/content-frontmatter.schema.json +81 -0
  62. package/schemas/manifest.json +9 -0
  63. package/schemas/sitewide-content.schema.json +215 -0
  64. package/schemas/theme.schema.json +1208 -0
  65. package/scripts/check-config.mjs +18 -11
  66. package/scripts/export-theme-preset.mjs +1 -1
  67. package/scripts/generate-schemas.mjs +283 -0
  68. package/scripts/init-site.mjs +22 -27
  69. package/scripts/lib/documentation-links.mjs +8 -0
  70. package/scripts/lib/editor-language-service.mjs +609 -0
  71. package/scripts/lib/example-sites.mjs +2 -2
  72. package/scripts/lib/git-status.mjs +7 -0
  73. package/scripts/lib/logo-assets.mjs +15 -10
  74. package/scripts/lib/norna-markdown-blocks.mjs +90 -11
  75. package/scripts/lib/presentation.mjs +23 -12
  76. package/scripts/lib/project-config.mjs +17 -41
  77. package/scripts/lib/public-asset-conventions.mjs +112 -0
  78. package/scripts/lib/schema-definitions.mjs +213 -0
  79. package/scripts/lib/schema-value-definitions.mjs +86 -0
  80. package/scripts/lib/site-content.mjs +24 -18
  81. package/scripts/lib/site-paths.mjs +4 -8
  82. package/scripts/lib/sitewide-content.mjs +24 -0
  83. package/scripts/lib/theme-config.mjs +15 -35
  84. package/scripts/lib/theme-presets.mjs +76 -66
  85. package/scripts/lib/typography.mjs +15 -15
  86. package/scripts/lib/yaml-config.mjs +50 -0
  87. package/scripts/list-theme-presets.mjs +15 -0
  88. package/scripts/release.mjs +84 -8
  89. package/scripts/show-typography.mjs +22 -46
  90. package/scripts/sync-content-sections.mjs +2 -2
  91. package/scripts/test-client-javascript.mjs +28 -28
  92. package/scripts/test-content-check.mjs +21 -26
  93. package/scripts/test-content-model-v2.mjs +72 -40
  94. package/scripts/test-documentation.mjs +70 -4
  95. package/scripts/test-editor-language-service.mjs +158 -0
  96. package/scripts/test-engine-commands.mjs +65 -34
  97. package/scripts/test-package-check.mjs +37 -30
  98. package/scripts/test-project-config.mjs +15 -20
  99. package/scripts/test-schemas.mjs +102 -0
  100. package/scripts/test-temporary-visibility.mjs +5 -13
  101. package/scripts/test-theme-presets.mjs +64 -37
  102. package/src/components/CardList.astro +2 -5
  103. package/src/components/ImageCarousel.astro +21 -21
  104. package/src/components/{GalleryGrid.astro → ImageStack.astro} +12 -12
  105. package/src/components/SectionNavigationScript.astro +28 -0
  106. package/src/components/SiteNavigation.astro +6 -5
  107. package/src/components/SitePage.astro +8 -8
  108. package/src/components/SiteSection.astro +18 -21
  109. package/src/content.config.ts +17 -209
  110. package/src/layouts/BaseLayout.astro +9 -9
  111. package/src/lib/{galleryImages.ts → imagePresentation.ts} +7 -7
  112. package/src/lib/routeThemes.ts +9 -29
  113. package/src/lib/sectionContent.ts +3 -3
  114. package/src/lib/sitePublicAssets.ts +5 -21
  115. package/src/styles/global.css +73 -73
  116. package/starters/basic/.github/workflows/deploy.yml +1 -1
  117. package/starters/basic/README.md +16 -13
  118. package/starters/basic/package.json +3 -2
  119. package/starters/basic/site/{config.md → config.yaml} +0 -2
  120. package/starters/basic/site/content.md +1 -1
  121. package/starters/basic/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  122. package/starters/basic/site/{theme.md → theme.yaml} +8 -15
  123. package/starters/project/.github/workflows/deploy.yml +1 -1
  124. package/starters/project/README.md +22 -15
  125. package/starters/project/package.json +3 -2
  126. package/starters/project/site/{config.md → config.yaml} +0 -2
  127. package/starters/project/site/{sitewide-content.md → sitewide-content.yaml} +1 -3
  128. package/starters/project/site/{theme.md → theme.yaml} +4 -8
  129. package/docs/site-structure.md +0 -98
  130. package/examples/complete-sites/dog-shelter-multi-page/site/sitewide-content.md +0 -16
  131. package/examples/complete-sites/dog-shelter-single-page/site/sitewide-content.md +0 -16
  132. package/examples/feature-demos/media-and-surfaces/site/routes/020-surfaces/theme.md +0 -8
  133. package/examples/feature-demos/theme-presets/site/config.md +0 -3
  134. package/examples/feature-demos/theme-presets/site/routes/030-project/theme.md +0 -3
  135. package/examples/feature-demos/theme-presets/site/theme.md +0 -3
  136. package/fixtures/content-model-v2/site/theme.md +0 -7
  137. package/scripts/lib/sitewide-config.mjs +0 -34
  138. package/src/components/MobileSectionNavigationScript.astro +0 -14
  139. /package/examples/complete-sites/dog-shelter-multi-page/site/routes/010-dogs/{route-content.md → content.md} +0 -0
  140. /package/examples/complete-sites/dog-shelter-multi-page/site/routes/020-adopt/{route-content.md → content.md} +0 -0
  141. /package/examples/feature-demos/media-and-surfaces/site/routes/010-media/{route-content.md → content.md} +0 -0
  142. /package/examples/feature-demos/theme-presets/site/routes/010-portfolio/{route-content.md → content.md} +0 -0
  143. /package/examples/feature-demos/theme-presets/site/routes/020-documentation/{route-content.md → content.md} +0 -0
  144. /package/examples/feature-demos/theme-presets/site/routes/030-project/{route-content.md → content.md} +0 -0
  145. /package/fixtures/content-model-v2/site/routes/010-guide/{route-content.md → content.md} +0 -0
  146. /package/starters/project/site/routes/010-guide/{route-content.md → content.md} +0 -0
@@ -1 +1 @@
1
- [["Map",1,2,9,10,91,92,112,113],"meta::meta",["Map",3,4,5,6,7,8],"astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":\"jsx\",\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":\"127.0.0.1\",\"port\":60863,\"allowedHosts\":[\"127.0.0.1\",\"127.0.0.1\",\"127.0.0.1\",\"127.0.0.1\"]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"dangerouslyProcessSVG\":false,\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"processor\":{\"name\":\"satteri\",\"options\":{\"mdastPlugins\":[],\"hastPlugins\":[],\"features\":{}}}},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[],\"csp\":false,\"actionBodySizeLimit\":1048576,\"serverIslandBodySizeLimit\":1048576},\"env\":{\"schema\":{},\"validateSecrets\":false},\"prerenderConflictBehavior\":\"warn\",\"fetchFile\":\"fetch\",\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"chromeDevtoolsWorkspace\":false,\"collectionStorage\":\"single-file\"},\"legacy\":{\"collectionsBackwardsCompat\":false}}","astro-version","7.1.3","content-config-digest","ef24ddbc7d731e37","site",["Map",11,12,35,36,63,64],"site-content",{"id":11,"data":13,"body":19,"filePath":20,"digest":21,"rendered":22},{"title":14,"description":15,"navigation":16,"sections":18},"Media and Surfaces","A visual test bench for Norna's managed media and presentation surfaces.",{"label":17},"Home",{},"## Media and surfaces {#intro}\n\nThis site is a focused test bench for Norna's managed media blocks, sidenotes,\npalettes and section-surface controls.\n\nUse [Media blocks](/media/) to compare image stacks, carousels, card lists and\nsidenotes. Use [Surfaces](/surfaces/) to inspect palettes and automatic section\nsurface sequences.\n\nSite identity, banners and footers have their own\n[sitewide content demo](https://janga.github.io/norna/examples/feature-demos/sitewide-content/).","site/content.md","78ec072eba5fb94d",{"html":23,"metadata":24},"\u003Ch2 id=\"media-and-surfaces-intro\">Media and surfaces {#intro}\u003C/h2>\n\u003Cp>This site is a focused test bench for Norna’s managed media blocks, sidenotes,\npalettes and section-surface controls.\u003C/p>\n\u003Cp>Use \u003Ca href=\"/media/\">Media blocks\u003C/a> to compare image stacks, carousels, card lists and\nsidenotes. Use \u003Ca href=\"/surfaces/\">Surfaces\u003C/a> to inspect palettes and automatic section\nsurface sequences.\u003C/p>\n\u003Cp>Site identity, banners and footers have their own\n\u003Ca href=\"https://janga.github.io/norna/examples/feature-demos/sitewide-content/\">sitewide content demo\u003C/a>.\u003C/p>\n",{"headings":25,"localImagePaths":30,"remoteImagePaths":31,"frontmatter":32,"imagePaths":34},[26],{"depth":27,"slug":28,"text":29},2,"media-and-surfaces-intro","Media and surfaces {#intro}",[],[],{"title":14,"description":15,"navigation":33},{"label":17},[],"site-route-010-media",{"id":35,"data":37,"body":42,"filePath":43,"digest":44,"rendered":45},{"title":38,"description":39,"navigation":40,"sections":41},"Media blocks","Compare Norna's managed image stacks, carousels and card lists.",{"label":38},{},"## Image stack {#stack}\n\nAn image stack places one or more managed images in the normal Markdown flow.\nEach source file belongs in the section's image folder, and Norna creates the\nresponsive output used by the browser.{note-ref}\n\n{note: Local image references are validated against the image folder for this section before the site is built.}\n\n```norna-image-stack\n- image: stack-one.svg\n alt: A pale panel with a single large circle.\n caption: One image can introduce a visual idea.\n- image: stack-two.svg\n alt: A dark panel with three aligned blocks.\n caption: A stack can contain several related images.\n```\n\n## Image carousel {#carousel}\n\nA carousel keeps a related group together while showing one image at a time.\nThe controls, keyboard interaction and current position are provided by\nNorna.{note-ref}\n\n{note: The carousel provides controls, keyboard interaction and readable position status without route-specific components.}\n\n```norna-image-carousel\n- image: carousel-one.svg\n alt: A green panel with a diagonal line.\n caption: First frame: a broad direction.\n- image: carousel-two.svg\n alt: A blue panel with two overlapping circles.\n caption: Second frame: a closer relationship.\n- image: carousel-three.svg\n alt: A red panel with a compact grid.\n caption: Third frame: a denser detail.\n```\n\n## Card list {#cards}\n\nCards are useful when several short items need the same visual treatment. The\nblock controls the layout and size without requiring a component for each\ncard.{note-ref}\n\n{note: Card layout stays within named options, so the same content remains predictable at narrow widths.}\n\n```norna-card-list\nlayout: image-top\nflow: grid\nsize: m\nwidth: normal\n\n- title: Prepare source files\n text: Keep related content and images together before building the site.\n image: card-stack.svg\n- title: Review presentation\n text: Check the result at wide and narrow browser widths.\n image: card-carousel.svg\n- title: Publish the result\n text: Build validated static output when the site is ready.\n image: card-surfaces.svg\n```\n\nEach example is an ordinary Markdown block with a bounded presentation model.","site/routes/010-media/route-content.md","05bcd9122ddb040c",{"html":46,"metadata":47},"\u003Ch2 id=\"image-stack-stack\">Image stack {#stack}\u003C/h2>\n\u003Cp>An image stack places one or more managed images in the normal Markdown flow.\nEach source file belongs in the section’s image folder, and Norna creates the\nresponsive output used by the browser.{note-ref}\u003C/p>\n\u003Cp>{note: Local image references are validated against the image folder for this section before the site is built.}\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>- image: stack-one.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A pale panel with a single large circle.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: One image can introduce a visual idea.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- image: stack-two.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A dark panel with three aligned blocks.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: A stack can contain several related images.\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"image-carousel-carousel\">Image carousel {#carousel}\u003C/h2>\n\u003Cp>A carousel keeps a related group together while showing one image at a time.\nThe controls, keyboard interaction and current position are provided by\nNorna.{note-ref}\u003C/p>\n\u003Cp>{note: The carousel provides controls, keyboard interaction and readable position status without route-specific components.}\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>- image: carousel-one.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A green panel with a diagonal line.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: First frame: a broad direction.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- image: carousel-two.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A blue panel with two overlapping circles.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: Second frame: a closer relationship.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- image: carousel-three.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A red panel with a compact grid.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: Third frame: a denser detail.\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"card-list-cards\">Card list {#cards}\u003C/h2>\n\u003Cp>Cards are useful when several short items need the same visual treatment. The\nblock controls the layout and size without requiring a component for each\ncard.{note-ref}\u003C/p>\n\u003Cp>{note: Card layout stays within named options, so the same content remains predictable at narrow widths.}\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>layout: image-top\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>flow: grid\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>size: m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>width: normal\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- title: Prepare source files\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> text: Keep related content and images together before building the site.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> image: card-stack.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- title: Review presentation\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> text: Check the result at wide and narrow browser widths.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> image: card-carousel.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- title: Publish the result\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> text: Build validated static output when the site is ready.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> image: card-surfaces.svg\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Each example is an ordinary Markdown block with a bounded presentation model.\u003C/p>\n",{"headings":48,"localImagePaths":58,"remoteImagePaths":59,"frontmatter":60,"imagePaths":62},[49,52,55],{"depth":27,"slug":50,"text":51},"image-stack-stack","Image stack {#stack}",{"depth":27,"slug":53,"text":54},"image-carousel-carousel","Image carousel {#carousel}",{"depth":27,"slug":56,"text":57},"card-list-cards","Card list {#cards}",[],[],{"title":38,"description":39,"navigation":61},{"label":38},[],"site-route-020-surfaces",{"id":63,"data":65,"body":70,"filePath":71,"digest":72,"rendered":73},{"title":66,"description":67,"navigation":68,"sections":69},"Surfaces","See how palette defaults and section surfaces work together.",{"label":66},{},"## Palette options {#palette-options}\n\nNorna provides a small set of named palettes. The theme chooses one\nfor the whole site:\n\n```yaml\npresentation:\n palette: dark\n```\n\nThe available choices are `dark`, `light` and `paper`. A palette defines the\npage, navigation, frame and section colours together, so these parts stay in\nbalance.\n\n## Emphasis surface {#emphasis-surface}\n\nThe route theme uses a palette and a surface sequence when a visual pause or\nchange of rhythm helps the reader. This is not a free-form colour override:\n\n```yaml\npresentation:\n sectionSurfaces:\n mode: cycle\n sequence: [base, soft, emphasis]\n```\n\nThe theme can cycle through the selected surfaces automatically. Individual\nsections do not select their own colours.\n\n## A practical rule {#practical-rule}\n\nUse the site palette for the overall tone. Use soft and emphasis surfaces for a\nsmall number of meaningful transitions, not to make every section look\nunrelated.\n\nTypography presets and media blocks can vary the content inside that system;\nsurfaces provide the route-level rhythm around it.","site/routes/020-surfaces/route-content.md","0566cc76e3c9f696",{"html":74,"metadata":75},"\u003Ch2 id=\"palette-options-palette-options\">Palette options {#palette-options}\u003C/h2>\n\u003Cp>Norna provides a small set of named palettes. The theme chooses one\nfor the whole site:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">presentation\u003C/span>\u003Cspan style=\"color:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> palette\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">dark\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>The available choices are \u003Ccode>dark\u003C/code>, \u003Ccode>light\u003C/code> and \u003Ccode>paper\u003C/code>. A palette defines the\npage, navigation, frame and section colours together, so these parts stay in\nbalance.\u003C/p>\n\u003Ch2 id=\"emphasis-surface-emphasis-surface\">Emphasis surface {#emphasis-surface}\u003C/h2>\n\u003Cp>The route theme uses a palette and a surface sequence when a visual pause or\nchange of rhythm helps the reader. This is not a free-form colour override:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">presentation\u003C/span>\u003Cspan style=\"color:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> sectionSurfaces\u003C/span>\u003Cspan style=\"color:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> mode\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">cycle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> sequence\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: [\u003C/span>\u003Cspan style=\"color:#9ECBFF\">base\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">soft\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">emphasis\u003C/span>\u003Cspan style=\"color:#E1E4E8\">]\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>The theme can cycle through the selected surfaces automatically. Individual\nsections do not select their own colours.\u003C/p>\n\u003Ch2 id=\"a-practical-rule-practical-rule\">A practical rule {#practical-rule}\u003C/h2>\n\u003Cp>Use the site palette for the overall tone. Use soft and emphasis surfaces for a\nsmall number of meaningful transitions, not to make every section look\nunrelated.\u003C/p>\n\u003Cp>Typography presets and media blocks can vary the content inside that system;\nsurfaces provide the route-level rhythm around it.\u003C/p>\n",{"headings":76,"localImagePaths":86,"remoteImagePaths":87,"frontmatter":88,"imagePaths":90},[77,80,83],{"depth":27,"slug":78,"text":79},"palette-options-palette-options","Palette options {#palette-options}",{"depth":27,"slug":81,"text":82},"emphasis-surface-emphasis-surface","Emphasis surface {#emphasis-surface}",{"depth":27,"slug":84,"text":85},"a-practical-rule-practical-rule","A practical rule {#practical-rule}",[],[],{"title":66,"description":67,"navigation":89},{"label":66},[],"sitewide",["Map",93,94],"site-sitewide",{"id":93,"data":95,"filePath":100,"digest":101,"rendered":102},{"navigation":96,"banners":97,"footer":98},{"brand":14},[],{"copyrightMessage":99},"Norna media and surfaces example.","site/sitewide-content.md","a62822e81bc10bcf",{"html":103,"metadata":104},"",{"headings":105,"localImagePaths":106,"remoteImagePaths":107,"frontmatter":108,"imagePaths":111},[],[],[],{"navigation":109,"footer":110},{"brand":14},{"copyrightMessage":99},[],"theme",["Map",114,115],"theme.md",{"id":114,"data":116,"filePath":118,"digest":119,"rendered":120},{"preset":117},"project","site/theme.md","d19ab283a10fb060",{"html":103,"metadata":121},{"headings":122,"localImagePaths":123,"remoteImagePaths":124,"frontmatter":125,"imagePaths":126},[],[],[],{"preset":117},[]]
1
+ [["Map",1,2,9,10,91,92,112,113],"meta::meta",["Map",3,4,5,6,7,8],"astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":\"jsx\",\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":\"127.0.0.1\",\"port\":61329,\"allowedHosts\":[\"127.0.0.1\",\"127.0.0.1\",\"127.0.0.1\",\"127.0.0.1\"]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"dangerouslyProcessSVG\":false,\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"processor\":{\"name\":\"satteri\",\"options\":{\"mdastPlugins\":[],\"hastPlugins\":[],\"features\":{}}}},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[],\"csp\":false,\"actionBodySizeLimit\":1048576,\"serverIslandBodySizeLimit\":1048576},\"env\":{\"schema\":{},\"validateSecrets\":false},\"prerenderConflictBehavior\":\"warn\",\"fetchFile\":\"fetch\",\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"chromeDevtoolsWorkspace\":false,\"collectionStorage\":\"single-file\"},\"legacy\":{\"collectionsBackwardsCompat\":false}}","astro-version","7.1.3","content-config-digest","ef24ddbc7d731e37","site",["Map",11,12,35,36,63,64],"site-content",{"id":11,"data":13,"body":19,"filePath":20,"digest":21,"rendered":22},{"title":14,"description":15,"navigation":16,"sections":18},"Media and Surfaces","A visual test bench for Norna's managed media and presentation surfaces.",{"label":17},"Home",{},"## Media and surfaces {#intro}\n\nThis site is a focused test bench for Norna's managed media blocks, sidenotes,\npalettes and section-surface controls.\n\nUse [Media blocks](/media/) to compare image stacks, carousels, card lists and\nsidenotes. Use [Surfaces](/surfaces/) to inspect palettes and automatic section\nsurface sequences.\n\nSite identity, banners and footers have their own\n[sitewide content demo](https://janga.github.io/norna/examples/feature-demos/sitewide-content/).","site/content.md","78ec072eba5fb94d",{"html":23,"metadata":24},"\u003Ch2 id=\"media-and-surfaces-intro\">Media and surfaces {#intro}\u003C/h2>\n\u003Cp>This site is a focused test bench for Norna’s managed media blocks, sidenotes,\npalettes and section-surface controls.\u003C/p>\n\u003Cp>Use \u003Ca href=\"/media/\">Media blocks\u003C/a> to compare image stacks, carousels, card lists and\nsidenotes. Use \u003Ca href=\"/surfaces/\">Surfaces\u003C/a> to inspect palettes and automatic section\nsurface sequences.\u003C/p>\n\u003Cp>Site identity, banners and footers have their own\n\u003Ca href=\"https://janga.github.io/norna/examples/feature-demos/sitewide-content/\">sitewide content demo\u003C/a>.\u003C/p>\n",{"headings":25,"localImagePaths":30,"remoteImagePaths":31,"frontmatter":32,"imagePaths":34},[26],{"depth":27,"slug":28,"text":29},2,"media-and-surfaces-intro","Media and surfaces {#intro}",[],[],{"title":14,"description":15,"navigation":33},{"label":17},[],"site-route-010-media",{"id":35,"data":37,"body":42,"filePath":43,"digest":44,"rendered":45},{"title":38,"description":39,"navigation":40,"sections":41},"Media blocks","Compare Norna's managed image stacks, carousels and card lists.",{"label":38},{},"## Image stack {#stack}\n\nAn image stack places one or more managed images in the normal Markdown flow.\nEach source file belongs in the section's image folder, and Norna creates the\nresponsive output used by the browser.{note-ref}\n\n{note: Local image references are validated against the image folder for this section before the site is built.}\n\n```norna-image-stack\n- image: stack-one.svg\n alt: A pale panel with a single large circle.\n caption: One image can introduce a visual idea.\n- image: stack-two.svg\n alt: A dark panel with three aligned blocks.\n caption: A stack can contain several related images.\n```\n\n## Image carousel {#carousel}\n\nA carousel keeps a related group together while showing one image at a time.\nThe controls, keyboard interaction and current position are provided by\nNorna.{note-ref}\n\n{note: The carousel provides controls, keyboard interaction and readable position status without route-specific components.}\n\n```norna-image-carousel\n- image: carousel-one.svg\n alt: A green panel with a diagonal line.\n caption: First frame: a broad direction.\n- image: carousel-two.svg\n alt: A blue panel with two overlapping circles.\n caption: Second frame: a closer relationship.\n- image: carousel-three.svg\n alt: A red panel with a compact grid.\n caption: Third frame: a denser detail.\n```\n\n## Card list {#cards}\n\nCards are useful when several short items need the same visual treatment. The\nblock controls the layout and size without requiring a component for each\ncard.{note-ref}\n\n{note: Card layout stays within named options, so the same content remains predictable at narrow widths.}\n\n```norna-card-list\nlayout: image-top\nflow: grid\nsize: m\nwidth: normal\n\n- title: Prepare source files\n text: Keep related content and images together before building the site.\n image: card-stack.svg\n- title: Review presentation\n text: Check the result at wide and narrow browser widths.\n image: card-carousel.svg\n- title: Publish the result\n text: Build validated static output when the site is ready.\n image: card-surfaces.svg\n```\n\nEach example is an ordinary Markdown block with a bounded presentation model.","site/routes/010-media/route-content.md","05bcd9122ddb040c",{"html":46,"metadata":47},"\u003Ch2 id=\"image-stack-stack\">Image stack {#stack}\u003C/h2>\n\u003Cp>An image stack places one or more managed images in the normal Markdown flow.\nEach source file belongs in the section’s image folder, and Norna creates the\nresponsive output used by the browser.{note-ref}\u003C/p>\n\u003Cp>{note: Local image references are validated against the image folder for this section before the site is built.}\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>- image: stack-one.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A pale panel with a single large circle.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: One image can introduce a visual idea.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- image: stack-two.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A dark panel with three aligned blocks.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: A stack can contain several related images.\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"image-carousel-carousel\">Image carousel {#carousel}\u003C/h2>\n\u003Cp>A carousel keeps a related group together while showing one image at a time.\nThe controls, keyboard interaction and current position are provided by\nNorna.{note-ref}\u003C/p>\n\u003Cp>{note: The carousel provides controls, keyboard interaction and readable position status without route-specific components.}\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>- image: carousel-one.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A green panel with a diagonal line.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: First frame: a broad direction.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- image: carousel-two.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A blue panel with two overlapping circles.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: Second frame: a closer relationship.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- image: carousel-three.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> alt: A red panel with a compact grid.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> caption: Third frame: a denser detail.\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"card-list-cards\">Card list {#cards}\u003C/h2>\n\u003Cp>Cards are useful when several short items need the same visual treatment. The\nblock controls the layout and size without requiring a component for each\ncard.{note-ref}\u003C/p>\n\u003Cp>{note: Card layout stays within named options, so the same content remains predictable at narrow widths.}\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>layout: image-top\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>flow: grid\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>size: m\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>width: normal\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- title: Prepare source files\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> text: Keep related content and images together before building the site.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> image: card-stack.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- title: Review presentation\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> text: Check the result at wide and narrow browser widths.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> image: card-carousel.svg\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan>- title: Publish the result\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> text: Build validated static output when the site is ready.\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan> image: card-surfaces.svg\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Each example is an ordinary Markdown block with a bounded presentation model.\u003C/p>\n",{"headings":48,"localImagePaths":58,"remoteImagePaths":59,"frontmatter":60,"imagePaths":62},[49,52,55],{"depth":27,"slug":50,"text":51},"image-stack-stack","Image stack {#stack}",{"depth":27,"slug":53,"text":54},"image-carousel-carousel","Image carousel {#carousel}",{"depth":27,"slug":56,"text":57},"card-list-cards","Card list {#cards}",[],[],{"title":38,"description":39,"navigation":61},{"label":38},[],"site-route-020-surfaces",{"id":63,"data":65,"body":70,"filePath":71,"digest":72,"rendered":73},{"title":66,"description":67,"navigation":68,"sections":69},"Surfaces","See how palette defaults and section surfaces work together.",{"label":66},{},"## Palette options {#palette-options}\n\nNorna provides a small set of named palettes. The theme chooses one\nfor the whole site:\n\n```yaml\npresentation:\n palette: dark\n```\n\nThe available choices are `dark`, `light` and `paper`. A palette defines the\npage, navigation, frame and section colours together, so these parts stay in\nbalance.\n\n## Emphasis surface {#emphasis-surface}\n\nThe route theme uses a palette and a surface sequence when a visual pause or\nchange of rhythm helps the reader. This is not a free-form colour override:\n\n```yaml\npresentation:\n sectionSurfaces:\n mode: cycle\n sequence: [base, soft, emphasis]\n```\n\nThe theme can cycle through the selected surfaces automatically. Individual\nsections do not select their own colours.\n\n## A practical rule {#practical-rule}\n\nUse the site palette for the overall tone. Use soft and emphasis surfaces for a\nsmall number of meaningful transitions, not to make every section look\nunrelated.\n\nTypography presets and media blocks can vary the content inside that system;\nsurfaces provide the route-level rhythm around it.","site/routes/020-surfaces/route-content.md","0566cc76e3c9f696",{"html":74,"metadata":75},"\u003Ch2 id=\"palette-options-palette-options\">Palette options {#palette-options}\u003C/h2>\n\u003Cp>Norna provides a small set of named palettes. The theme chooses one\nfor the whole site:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">presentation\u003C/span>\u003Cspan style=\"color:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> palette\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">dark\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>The available choices are \u003Ccode>dark\u003C/code>, \u003Ccode>light\u003C/code> and \u003Ccode>paper\u003C/code>. A palette defines the\npage, navigation, frame and section colours together, so these parts stay in\nbalance.\u003C/p>\n\u003Ch2 id=\"emphasis-surface-emphasis-surface\">Emphasis surface {#emphasis-surface}\u003C/h2>\n\u003Cp>The route theme uses a palette and a surface sequence when a visual pause or\nchange of rhythm helps the reader. This is not a free-form colour override:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"yaml\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">presentation\u003C/span>\u003Cspan style=\"color:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> sectionSurfaces\u003C/span>\u003Cspan style=\"color:#E1E4E8\">:\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> mode\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">cycle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\"> sequence\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: [\u003C/span>\u003Cspan style=\"color:#9ECBFF\">base\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">soft\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">emphasis\u003C/span>\u003Cspan style=\"color:#E1E4E8\">]\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>The theme can cycle through the selected surfaces automatically. Individual\nsections do not select their own colours.\u003C/p>\n\u003Ch2 id=\"a-practical-rule-practical-rule\">A practical rule {#practical-rule}\u003C/h2>\n\u003Cp>Use the site palette for the overall tone. Use soft and emphasis surfaces for a\nsmall number of meaningful transitions, not to make every section look\nunrelated.\u003C/p>\n\u003Cp>Typography presets and media blocks can vary the content inside that system;\nsurfaces provide the route-level rhythm around it.\u003C/p>\n",{"headings":76,"localImagePaths":86,"remoteImagePaths":87,"frontmatter":88,"imagePaths":90},[77,80,83],{"depth":27,"slug":78,"text":79},"palette-options-palette-options","Palette options {#palette-options}",{"depth":27,"slug":81,"text":82},"emphasis-surface-emphasis-surface","Emphasis surface {#emphasis-surface}",{"depth":27,"slug":84,"text":85},"a-practical-rule-practical-rule","A practical rule {#practical-rule}",[],[],{"title":66,"description":67,"navigation":89},{"label":66},[],"sitewide",["Map",93,94],"site-sitewide",{"id":93,"data":95,"filePath":100,"digest":101,"rendered":102},{"navigation":96,"banners":97,"footer":98},{"brand":14},[],{"copyrightMessage":99},"Norna media and surfaces example.","site/sitewide-content.md","a62822e81bc10bcf",{"html":103,"metadata":104},"",{"headings":105,"localImagePaths":106,"remoteImagePaths":107,"frontmatter":108,"imagePaths":111},[],[],[],{"navigation":109,"footer":110},{"brand":14},{"copyrightMessage":99},[],"theme",["Map",114,115],"theme.md",{"id":114,"data":116,"filePath":118,"digest":119,"rendered":120},{"preset":117},"project","site/theme.md","d19ab283a10fb060",{"html":103,"metadata":121},{"headings":122,"localImagePaths":123,"remoteImagePaths":124,"frontmatter":125,"imagePaths":126},[],[],[],{"preset":117},[]]
@@ -16,6 +16,6 @@ Run it from the repository root with:
16
16
  node bin/norna.mjs --site-dir examples/feature-demos/media-and-surfaces/site dev:local
17
17
  ```
18
18
 
19
- The site has a home page plus routes for media blocks and surfaces. Sitewide
19
+ The site has a home page plus routes for Norna blocks and surfaces. Sitewide
20
20
  identity, banners and footers are demonstrated separately in
21
21
  `examples/feature-demos/sitewide-content/`.
@@ -1,3 +1 @@
1
- ---
2
1
  url: http://localhost:4321/
3
- ---
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  title: Media and Surfaces
3
- description: A visual test bench for Norna's managed media and presentation surfaces.
3
+ description: A visual test bench for Norna's image and card blocks and presentation surfaces.
4
4
  navigation:
5
5
  label: Home
6
6
  ---
7
7
 
8
8
  ## Media and surfaces {#intro}
9
9
 
10
- This site is a focused test bench for Norna's managed media blocks, sidenotes,
10
+ This site is a focused test bench for Norna's image and card blocks, sidenotes,
11
11
  palettes and section-surface controls.
12
12
 
13
13
  Use [Media blocks](/media/) to compare image stacks, carousels, card lists and
@@ -11,8 +11,7 @@ Norna provides a small set of named palettes. The theme chooses one
11
11
  for the whole site:
12
12
 
13
13
  ```yaml
14
- presentation:
15
- palette: dark
14
+ palette: dark
16
15
  ```
17
16
 
18
17
  The available choices are `dark`, `light` and `paper`. A palette defines the
@@ -25,10 +24,7 @@ The route theme uses a palette and a surface sequence when a visual pause or
25
24
  change of rhythm helps the reader. This is not a free-form colour override:
26
25
 
27
26
  ```yaml
28
- presentation:
29
- sectionSurfaces:
30
- mode: cycle
31
- sequence: [base, soft, emphasis]
27
+ sectionSurfaces: [base, soft, emphasis]
32
28
  ```
33
29
 
34
30
  The theme can cycle through the selected surfaces automatically. Individual
@@ -40,5 +36,5 @@ Use the site palette for the overall tone. Use soft and emphasis surfaces for a
40
36
  small number of meaningful transitions, not to make every section look
41
37
  unrelated.
42
38
 
43
- Typography presets and media blocks can vary the content inside that system;
39
+ Typography profiles and Norna blocks can vary the content inside that system;
44
40
  surfaces provide the route-level rhythm around it.
@@ -0,0 +1,3 @@
1
+ preset: project
2
+ palette: light
3
+ sectionSurfaces: [base, soft, emphasis]
@@ -1,6 +1,4 @@
1
- ---
2
1
  navigation:
3
- brand: Media and Surfaces
2
+ label: Media and Surfaces
4
3
  footer:
5
4
  copyrightMessage: Norna media and surfaces example.
6
- ---
@@ -16,3 +16,11 @@ node bin/norna.mjs --site-dir examples/feature-demos/sitewide-content/site dev:l
16
16
 
17
17
  Move between the routes to verify that the same sitewide elements remain in
18
18
  place. Banner dismissals are stored locally in the browser.
19
+
20
+ <!-- norna-image-provenance:
21
+ image: site/public/logo.svg
22
+ source: AI-assisted, hand-authored SVG
23
+ prompt: Create a compact horizontal logo named Shared Frame. Use a simple
24
+ overlapping-frame symbol, dark text, one muted red accent, a transparent
25
+ background and no external assets.
26
+ -->
@@ -1,3 +1 @@
1
- ---
2
1
  url: http://localhost:4321/
3
- ---
@@ -8,11 +8,11 @@ navigation:
8
8
  ## One identity across routes {#identity}
9
9
 
10
10
  The logo in the navigation is discovered from `public/logo.svg`. Its alt text
11
- and display height belong to `sitewide-content.md`, because the identity is
11
+ and display height belong to `sitewide-content.yaml`, because the identity is
12
12
  shared by every route.
13
13
 
14
- If a site has no logo file, Norna can use a text brand instead. A route cannot
15
- replace the site identity with its own logo or brand.
14
+ If a site has no logo file, Norna shows the navigation label as text instead. A
15
+ route cannot replace the shared navigation identity.
16
16
 
17
17
  ## Navigation context {#navigation}
18
18
 
@@ -7,7 +7,7 @@ navigation:
7
7
 
8
8
  ## Banner stack {#banner-stack}
9
9
 
10
- The two notices above the page content are defined in `sitewide-content.md`.
10
+ The two notices above the page content are defined in `sitewide-content.yaml`.
11
11
  List order controls their order, and each notice keeps its own identity.
12
12
 
13
13
  ## Dismissal {#dismissal}
@@ -7,7 +7,7 @@ navigation:
7
7
 
8
8
  ## Persistent footer content {#footer-content}
9
9
 
10
- The footer below this page is defined once in `sitewide-content.md`. Its
10
+ The footer below this page is defined once in `sitewide-content.yaml`. Its
11
11
  copyright message remains the same across routes.
12
12
 
13
13
  ## Build information {#build-information}
@@ -1,7 +1,6 @@
1
- ---
2
1
  navigation:
2
+ label: Shared Frame
3
3
  logo:
4
- alt: Shared Frame
5
4
  height: 2.8rem
6
5
  banners:
7
6
  - id: preview-environment
@@ -22,12 +21,3 @@ footer:
22
21
  timeZone: UTC
23
22
  dateStyle: medium
24
23
  timeStyle: short
25
- ---
26
-
27
- <!-- norna-image-provenance:
28
- image: logo.svg
29
- source: AI-assisted, hand-authored SVG
30
- prompt: Create a compact horizontal logo named Shared Frame. Use a simple
31
- overlapping-frame symbol, dark text, one muted red accent, a transparent
32
- background and no external assets.
33
- -->
@@ -0,0 +1 @@
1
+ url: http://localhost:4321/
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Statement
3
- description: A stronger typography preset for short declarative content.
3
+ description: A stronger typography profile for short declarative content.
4
4
  navigation:
5
5
  label: Statement
6
6
  ---
@@ -1,6 +1,5 @@
1
- ---
2
1
  navigation:
3
- brand: Theme Presets
2
+ label: Theme Presets
4
3
  footer:
5
4
  copyrightMessage: Dog photos by Bicanski, CC0, via Pixnio.
6
5
  buildInfo:
@@ -11,4 +10,3 @@ footer:
11
10
  timeZone: UTC
12
11
  dateStyle: short
13
12
  timeStyle: short
14
- ---
@@ -0,0 +1 @@
1
+ preset: project
@@ -1,3 +1 @@
1
- ---
2
1
  url: https://example.com/
3
- ---
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Fixture Site
3
- description: Minimal cli-gallery fixture site.
3
+ description: Minimal Norna fixture site.
4
4
  sections:
5
5
  intro: {}
6
6
  work: {}
@@ -8,8 +8,8 @@ sections:
8
8
  ---
9
9
  ## Intro {#intro}
10
10
 
11
- This fixture validates the cli-gallery engine against a stable empty gallery.
11
+ This fixture validates the Norna engine against a stable page without managed images.
12
12
 
13
13
  ## Work {#work}
14
14
 
15
- Fixture section with no gallery images.
15
+ Fixture section with no managed images.
@@ -1,4 +1,3 @@
1
- ---
2
1
  footer:
3
2
  copyrightMessage: (c) Fixture Artist.
4
3
  buildInfo:
@@ -9,4 +8,3 @@ footer:
9
8
  timeZone: UTC
10
9
  dateStyle: short
11
10
  timeStyle: short
12
- ---
@@ -1,11 +1,8 @@
1
- ---
2
1
  layout:
3
2
  pageWidth: 1180px
4
- gallery:
3
+ images:
5
4
  width: 900px
6
5
  typography:
7
6
  fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
8
- preset: quiet-gallery
9
- presentation:
10
- palette: dark
11
- ---
7
+ profile: restrained
8
+ palette: dark
@@ -1,3 +1 @@
1
- ---
2
1
  url: https://example.com/
3
- ---
@@ -0,0 +1,4 @@
1
+ typography:
2
+ profile: reading
3
+ rhythm: normal
4
+ palette: dark
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@janga/norna",
3
3
  "description": "An opinionated CLI for building responsive websites from Markdown, images, and theme presets.",
4
4
  "type": "module",
5
- "version": "0.7.13",
5
+ "version": "0.7.15",
6
6
  "license": "GPL-3.0-only",
7
7
  "repository": {
8
8
  "type": "git",
@@ -30,6 +30,7 @@
30
30
  "examples/",
31
31
  "fixtures/",
32
32
  "scripts/",
33
+ "schemas/",
33
34
  "src/",
34
35
  "starters/",
35
36
  "!**/.norna/public/",
@@ -53,10 +54,13 @@
53
54
  "config:check": "node bin/norna.mjs config:check",
54
55
  "content:check": "node bin/norna.mjs content:check",
55
56
  "content:sync": "node bin/norna.mjs content:sync",
57
+ "theme:presets": "node bin/norna.mjs theme:presets",
56
58
  "theme:export": "node bin/norna.mjs theme:export",
57
- "typography:presets": "node bin/norna.mjs typography presets",
59
+ "typography:profiles": "node bin/norna.mjs typography profiles",
58
60
  "typography:show": "node bin/norna.mjs typography show",
59
61
  "site:public": "node bin/norna.mjs site:public",
62
+ "schemas:generate": "node scripts/generate-schemas.mjs",
63
+ "schemas:check": "node scripts/generate-schemas.mjs --check",
60
64
  "images": "node bin/norna.mjs images",
61
65
  "build": "node bin/norna.mjs build",
62
66
  "build:pages": "node scripts/build-pages.mjs",
@@ -66,10 +70,11 @@
66
70
  "deploy:watch": "node bin/norna.mjs deploy:watch",
67
71
  "doctor": "node bin/norna.mjs doctor",
68
72
  "demo:build": "node bin/norna.mjs --site-dir examples/feature-demos/media-and-surfaces/site build",
69
- "test": "npm run test:route-model && npm run test:project-config && npm run test:content-check && npm run test:content-model-v2 && npm run test:theme-presets && npm run test:site-public && npm run test:cli-discovery && npm run test:engine-commands && npm run test:documentation && npm run test:ci-lockfile && npm run test:temporary-visibility && npm run test:client-javascript && npm run test:fixture:build && npm run test:examples && npm run package:check",
73
+ "test": "npm run schemas:check && npm run test:schemas && npm run test:route-model && npm run test:project-config && npm run test:editor-language && npm run test:content-check && npm run test:content-model-v2 && npm run test:theme-presets && npm run test:site-public && npm run test:cli-discovery && npm run test:engine-commands && npm run test:documentation && npm run test:ci-lockfile && npm run test:temporary-visibility && npm run test:client-javascript && npm run test:fixture:build && npm run test:examples && npm run package:check",
70
74
  "test:fixture:build": "node bin/norna.mjs --site-dir fixtures/basic/site build",
71
75
  "test:examples": "node scripts/test-examples.mjs",
72
76
  "test:route-model": "node scripts/test-route-model.mjs",
77
+ "test:schemas": "node scripts/test-schemas.mjs",
73
78
  "test:project-config": "node scripts/test-project-config.mjs",
74
79
  "test:content-check": "node scripts/test-content-check.mjs",
75
80
  "test:content-model-v2": "node scripts/test-content-model-v2.mjs",
@@ -77,6 +82,7 @@
77
82
  "test:site-public": "node scripts/test-site-public.mjs",
78
83
  "test:cli-discovery": "node scripts/test-cli-discovery.mjs",
79
84
  "test:engine-commands": "node scripts/test-engine-commands.mjs",
85
+ "test:editor-language": "node scripts/test-editor-language-service.mjs && npm --prefix editors/vscode run check",
80
86
  "test:documentation": "node scripts/test-documentation.mjs",
81
87
  "test:ci-lockfile": "node scripts/test-ci-lockfile.mjs",
82
88
  "test:temporary-visibility": "node scripts/test-temporary-visibility.mjs",
@@ -95,6 +101,7 @@
95
101
  "dependencies": {
96
102
  "astro": "^7.1.3",
97
103
  "embla-carousel": "^8.6.0",
104
+ "js-yaml": "^4.3.1",
98
105
  "satteri": "^0.9.1"
99
106
  },
100
107
  "devDependencies": {
@@ -0,0 +1,77 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "url": {
6
+ "type": "string",
7
+ "format": "uri",
8
+ "description": "Absolute public URL for the built site.",
9
+ "markdownDescription": "```yaml\nurl: https://example.com/\n```\n\nThe absolute public URL. Its path also determines the base path for generated links and assets.\n\n[Public URL reference](https://github.com/janga/norna/blob/v0.7.15/docs/configuration.md#url)",
10
+ "examples": [
11
+ "https://example.com/",
12
+ "https://owner.github.io/repository-name/"
13
+ ]
14
+ },
15
+ "language": {
16
+ "description": "Site language tag using Norna's English or Swedish interface text; the default is en.",
17
+ "type": "string",
18
+ "pattern": "^(?:en|sv)(?:-[a-zA-Z0-9]+)*$",
19
+ "default": "en",
20
+ "examples": [
21
+ "en",
22
+ "sv",
23
+ "en-GB",
24
+ "sv-SE"
25
+ ],
26
+ "oneOf": [
27
+ {
28
+ "const": "en",
29
+ "title": "English",
30
+ "description": "Use Norna's built-in English interface text."
31
+ },
32
+ {
33
+ "const": "sv",
34
+ "title": "Swedish",
35
+ "description": "Use Norna's built-in Swedish interface text."
36
+ },
37
+ {
38
+ "type": "string",
39
+ "pattern": "^(?:en|sv)-[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*$",
40
+ "title": "Regional language tag",
41
+ "description": "Use an English or Swedish regional language tag such as en-GB or sv-SE."
42
+ }
43
+ ],
44
+ "markdownDescription": "```yaml\nlanguage: en-GB\n```\n\nSets the page language and selects Norna's built-in English or Swedish interface text. The default is `en`.\n\n[Language reference](https://github.com/janga/norna/blob/v0.7.15/docs/configuration.md#language)"
45
+ },
46
+ "scrollBehavior": {
47
+ "default": "instant",
48
+ "description": "Use instant anchors by default or the browser's native smooth scrolling.",
49
+ "type": "string",
50
+ "oneOf": [
51
+ {
52
+ "const": "instant",
53
+ "title": "Instant",
54
+ "description": "Jump directly to anchors without animated scrolling. This is the default."
55
+ },
56
+ {
57
+ "const": "smooth",
58
+ "title": "Browser smooth",
59
+ "description": "Use the browser's native smooth scrolling for anchor navigation."
60
+ }
61
+ ],
62
+ "markdownDescription": "```yaml\nscrollBehavior: smooth\n```\n\nControls same-page anchor movement. `instant` is the default; `smooth` uses the browser's native smooth scrolling.\n\n[Scroll behavior reference](https://github.com/janga/norna/blob/v0.7.15/docs/configuration.md#scrollbehavior)",
63
+ "examples": [
64
+ "instant",
65
+ "smooth"
66
+ ]
67
+ }
68
+ },
69
+ "required": [
70
+ "url"
71
+ ],
72
+ "additionalProperties": false,
73
+ "description": "Technical settings for one Norna site. Routes cannot provide technical configuration.",
74
+ "$id": "https://janga.github.io/norna/schemas/config.schema.json",
75
+ "title": "Norna site configuration",
76
+ "markdownDescription": "```yaml\nurl: https://example.com/\n```\n\n`config.yaml` contains the few technical settings shared by the complete site.\n\n[Configuration reference](https://github.com/janga/norna/blob/v0.7.15/docs/configuration.md)"
77
+ }
@@ -0,0 +1,81 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "title": {
6
+ "type": "string",
7
+ "description": "Page title used in metadata and route navigation.",
8
+ "markdownDescription": "```yaml\ntitle: About\n```\n\nThe page title used in metadata and, by default, route navigation.\n\n[Page frontmatter reference](https://github.com/janga/norna/blob/v0.7.15/docs/content.md#page-frontmatter)",
9
+ "examples": [
10
+ "About"
11
+ ]
12
+ },
13
+ "description": {
14
+ "type": "string",
15
+ "description": "Page description used in metadata.",
16
+ "markdownDescription": "```yaml\ndescription: About this project.\n```\n\nA concise page description used in metadata.\n\n[Page frontmatter reference](https://github.com/janga/norna/blob/v0.7.15/docs/content.md#page-frontmatter)",
17
+ "examples": [
18
+ "About this project."
19
+ ]
20
+ },
21
+ "navigation": {
22
+ "description": "Optional navigation metadata for this page.",
23
+ "type": "object",
24
+ "properties": {
25
+ "include": {
26
+ "description": "Include this page in site navigation. Pages are included when omitted.",
27
+ "type": "boolean"
28
+ },
29
+ "label": {
30
+ "description": "Navigation label when it should differ from the page title.",
31
+ "type": "string"
32
+ }
33
+ },
34
+ "additionalProperties": false,
35
+ "markdownDescription": "```yaml\nnavigation:\n include: true\n label: About us\n```\n\nControls whether a route appears in site navigation and optionally replaces its visible title there. Homepage navigation is section-based.\n\n[Route navigation reference](https://github.com/janga/norna/blob/v0.7.15/docs/routes.md#navigation)"
36
+ },
37
+ "sections": {
38
+ "default": {},
39
+ "description": "Optional metadata keyed by Markdown section id. Do not duplicate section order here.",
40
+ "type": "object",
41
+ "propertyNames": {
42
+ "type": "string",
43
+ "pattern": "^[a-z0-9-]+$"
44
+ },
45
+ "additionalProperties": {
46
+ "type": "object",
47
+ "properties": {
48
+ "visible": {
49
+ "description": "Optional date window for this section.",
50
+ "type": "object",
51
+ "properties": {
52
+ "from": {
53
+ "description": "First date on which the content is visible.",
54
+ "type": "string",
55
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
56
+ },
57
+ "until": {
58
+ "description": "First date on which the content is no longer visible.",
59
+ "type": "string",
60
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
61
+ }
62
+ },
63
+ "additionalProperties": false
64
+ }
65
+ },
66
+ "additionalProperties": false,
67
+ "description": "Metadata keyed by the explicit Markdown section id. Markdown order remains authoritative."
68
+ },
69
+ "markdownDescription": "```yaml\nsections:\n announcement:\n visible:\n until: \"2026-12-01\"\n```\n\nAdds optional metadata keyed by explicit Markdown section id. Markdown headings remain the source of section content and order.\n\n[Section metadata reference](https://github.com/janga/norna/blob/v0.7.15/docs/content.md#section-metadata)"
70
+ }
71
+ },
72
+ "required": [
73
+ "title",
74
+ "description"
75
+ ],
76
+ "additionalProperties": false,
77
+ "description": "Frontmatter for a homepage or route content.md file.",
78
+ "$id": "https://janga.github.io/norna/schemas/content-frontmatter.schema.json",
79
+ "title": "Norna page frontmatter",
80
+ "markdownDescription": "```yaml\n---\ntitle: About\ndescription: About this project.\n---\n```\n\nEvery homepage and route `content.md` starts with page metadata, followed by Markdown sections.\n\n[Page frontmatter reference](https://github.com/janga/norna/blob/v0.7.15/docs/content.md#page-frontmatter)"
81
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "files": {
4
+ "config": "config.schema.json",
5
+ "contentFrontmatter": "content-frontmatter.schema.json",
6
+ "sitewideContent": "sitewide-content.schema.json",
7
+ "theme": "theme.schema.json"
8
+ }
9
+ }