@janga/norna 0.7.22 → 0.7.23

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 (60) hide show
  1. package/astro.config.mjs +3 -0
  2. package/bin/norna-cli.mjs +2 -2
  3. package/package.json +17 -3
  4. package/schemas/category.schema.json +2 -2
  5. package/schemas/config.schema.json +22 -24
  6. package/schemas/content-frontmatter.schema.json +25 -5
  7. package/schemas/page-theme.schema.json +53 -25
  8. package/schemas/sitewide-content.schema.json +19 -18
  9. package/schemas/theme.schema.json +383 -250
  10. package/scripts/check-config.mjs +24 -4
  11. package/scripts/deploy-site.mjs +0 -1
  12. package/scripts/dev-local.mjs +175 -112
  13. package/scripts/lib/content-sync-apply.mjs +34 -0
  14. package/scripts/lib/content-sync-plan.mjs +179 -0
  15. package/scripts/lib/editor-language-service.mjs +128 -0
  16. package/scripts/lib/heading-ids.mjs +1 -1
  17. package/scripts/lib/image-presentation.mjs +2 -0
  18. package/scripts/lib/markdown-links.mjs +182 -0
  19. package/scripts/lib/navigation-model.mjs +25 -14
  20. package/scripts/lib/norna-markdown-blocks.mjs +1 -0
  21. package/scripts/lib/page-aliases.mjs +164 -0
  22. package/scripts/lib/page-markdown.mjs +56 -6
  23. package/scripts/lib/presentation.mjs +19 -37
  24. package/scripts/lib/project-config.mjs +50 -29
  25. package/scripts/lib/schema-definitions.mjs +24 -13
  26. package/scripts/lib/schema-editor-metadata.mjs +43 -30
  27. package/scripts/lib/schema-value-definitions.mjs +6 -2
  28. package/scripts/lib/site-content.mjs +26 -4
  29. package/scripts/lib/site-link-graph.mjs +326 -0
  30. package/scripts/lib/site-page-urls.mjs +10 -0
  31. package/scripts/lib/sitemap.mjs +34 -0
  32. package/scripts/lib/theme-presets.mjs +51 -23
  33. package/scripts/lib/theme-profiles.mjs +7 -5
  34. package/scripts/lib/yaml-config.mjs +6 -2
  35. package/scripts/sync-content-sections.mjs +116 -213
  36. package/scripts/sync-site-public.mjs +23 -2
  37. package/src/components/CodeBlockCopyScript.astro +92 -0
  38. package/src/components/DisplaySettings.astro +4 -4
  39. package/src/components/ImageCarousel.astro +7 -3
  40. package/src/components/NavigationPageTree.astro +44 -60
  41. package/src/components/PageAliasRedirect.astro +49 -0
  42. package/src/components/PageContentsNavigation.astro +21 -0
  43. package/src/components/SectionNavigationScript.astro +62 -6
  44. package/src/components/SiteNavigation.astro +15 -3
  45. package/src/components/SitePage.astro +42 -2
  46. package/src/components/SiteSection.astro +5 -0
  47. package/src/components/SiteTreeNavigation.astro +0 -1
  48. package/src/content.config.ts +5 -2
  49. package/src/layouts/BaseLayout.astro +14 -8
  50. package/src/lib/readerPreferencesScript.mjs +2 -2
  51. package/src/lib/sitePages.ts +3 -2
  52. package/src/pages/[...slug].astro +35 -8
  53. package/src/styles/content.css +494 -0
  54. package/src/styles/foundations.css +284 -0
  55. package/src/styles/global.css +6 -2510
  56. package/src/styles/media.css +523 -0
  57. package/src/styles/navigation.css +495 -0
  58. package/src/styles/page-layout.css +437 -0
  59. package/src/styles/responsive.css +525 -0
  60. package/starters/basic/README.md +1 -1
package/astro.config.mjs CHANGED
@@ -144,6 +144,9 @@ export default defineConfig({
144
144
  publicDir: astroPublicDir,
145
145
  srcDir: path.join(engineRoot, 'src'),
146
146
  vite: {
147
+ server: {
148
+ strictPort: true,
149
+ },
147
150
  plugins: [nornaBasePathRedirect(), nornaGeneratedImagesWatcher()],
148
151
  },
149
152
  });
package/bin/norna-cli.mjs CHANGED
@@ -8,8 +8,8 @@ const usage = `
8
8
  Usage: norna <command> [options]
9
9
 
10
10
  Commands:
11
- dev:local Start local Astro dev server
12
- dev:lan Start dev server for this local network
11
+ dev:local [--kill] Start local Astro dev server on the configured port
12
+ dev:lan [--kill] Start LAN dev server on the configured port
13
13
  dev:restart Restart local Astro dev server
14
14
  dev:status Show local dev server status
15
15
  dev:logs Show local dev server logs
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.22",
5
+ "version": "0.7.23",
6
6
  "license": "GPL-3.0-only",
7
7
  "repository": {
8
8
  "type": "git",
@@ -88,11 +88,14 @@
88
88
  "deploy:watch": "node bin/norna.mjs deploy:watch",
89
89
  "doctor": "node bin/norna.mjs doctor",
90
90
  "demo:build": "node scripts/build-demo.mjs",
91
- "test": "npm run schemas:check && npm run test:dead-code && npm run test:schemas && npm run test:page-model && npm run test:page-markdown && npm run test:site-node-commands && npm run test:nested-pages && npm run test:heading-ids && npm run test:navigation-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:presentation-contract && npm run test:preset-baselines && npm run test:documentation-preset-review && 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:banner-visibility && npm run test:client-javascript && npm run test:fixture:build && npm run test:examples && npm run package:check",
91
+ "test": "npm run schemas:check && npm run test:dead-code && npm run test:schemas && npm run test:page-model && npm run test:page-markdown && npm run test:site-links && npm run test:page-aliases && npm run test:sitemap && npm run test:site-node-commands && npm run test:nested-pages && npm run test:heading-ids && npm run test:navigation-model && npm run test:project-config && npm run test:editor-language && npm run test:content-check && npm run test:content-sync-plan && npm run test:content-model && npm run test:theme-presets && npm run test:presentation-contract && npm run test:preset-baselines && npm run test:documentation-preset-review && npm run test:site-public && npm run test:cli-discovery && npm run test:dev-local && npm run test:engine-commands && npm run test:documentation && npm run test:ci-lockfile && npm run test:banner-visibility && npm run test:client-javascript && npm run test:fixture:build && npm run test:examples && npm run package:check",
92
92
  "test:fixture:build": "node scripts/test-basic-fixture-build.mjs",
93
93
  "test:examples": "node scripts/test-examples.mjs",
94
94
  "test:page-model": "node scripts/test-page-model.mjs",
95
95
  "test:page-markdown": "node scripts/test-page-markdown.mjs",
96
+ "test:site-links": "node scripts/test-site-link-graph.mjs",
97
+ "test:page-aliases": "node scripts/test-page-aliases.mjs",
98
+ "test:sitemap": "node scripts/test-sitemap.mjs",
96
99
  "test:site-node-commands": "node scripts/test-site-node-commands.mjs",
97
100
  "test:nested-pages": "node scripts/test-nested-pages.mjs",
98
101
  "test:heading-ids": "node scripts/test-heading-ids.mjs",
@@ -100,10 +103,18 @@
100
103
  "test:schemas": "node scripts/test-schemas.mjs",
101
104
  "test:project-config": "node scripts/test-project-config.mjs",
102
105
  "test:content-check": "node scripts/test-content-check.mjs",
103
- "test:content-model-v2": "node scripts/test-content-model-v2.mjs",
106
+ "test:content-sync-plan": "node scripts/test-content-sync-plan.mjs",
107
+ "test:content-model": "npm run test:page-content && npm run test:managed-media && npm run test:content-sync && npm run test:markdown-constructs",
108
+ "test:page-content": "node scripts/test-page-content.mjs",
109
+ "test:managed-media": "node scripts/test-managed-media.mjs",
110
+ "test:content-sync": "node scripts/test-content-sync.mjs",
111
+ "test:markdown-constructs": "node scripts/test-markdown-constructs.mjs",
104
112
  "test:theme-presets": "node scripts/test-theme-presets.mjs",
105
113
  "test:presentation-contract": "node scripts/test-presentation-contract.mjs",
106
114
  "test:presentation:browser": "node scripts/test-navigation.mjs --site-dir fixtures/preset-baseline/site tests/presentation-contract.spec.ts",
115
+ "test:navigation-surfaces:browser": "npm run test:navigation-surfaces:top && npm run test:navigation-surfaces:tree",
116
+ "test:navigation-surfaces:top": "node scripts/test-navigation.mjs --site-dir fixtures/content-model-v2/site tests/navigation-surfaces-top.spec.ts",
117
+ "test:navigation-surfaces:tree": "node scripts/test-navigation.mjs --site-dir fixtures/preset-baseline/site tests/presentation-contract.spec.ts",
107
118
  "test:preset-baselines": "node scripts/test-preset-baselines.mjs",
108
119
  "test:documentation-preset-review": "node scripts/test-documentation-preset-review.mjs",
109
120
  "preset:baselines:capture": "node scripts/test-preset-baselines.mjs --capture",
@@ -113,8 +124,11 @@
113
124
  "palette:review:build": "node scripts/review-documentation-preset.mjs --palettes --build-only",
114
125
  "test:site-public": "node scripts/test-site-public.mjs",
115
126
  "test:cli-discovery": "node scripts/test-cli-discovery.mjs",
127
+ "test:dev-local": "node scripts/test-dev-local.mjs",
116
128
  "test:engine-commands": "node scripts/test-engine-commands.mjs",
117
129
  "test:editor-language": "node scripts/test-editor-language-service.mjs && npm --prefix editors/vscode run check",
130
+ "test:editor-integration": "npm --prefix editors/vscode run test:integration",
131
+ "test:editor-integration:minimum": "npm --prefix editors/vscode run test:integration:minimum",
118
132
  "test:documentation": "node scripts/test-documentation.mjs",
119
133
  "test:ci-lockfile": "node scripts/test-ci-lockfile.mjs",
120
134
  "test:banner-visibility": "node scripts/test-banner-visibility.mjs",
@@ -6,7 +6,7 @@
6
6
  "type": "string",
7
7
  "minLength": 1,
8
8
  "description": "Navigation label for this non-routable page category.",
9
- "markdownDescription": "```yaml\nlabel: Guides\n```\n\nThe category label shown in global navigation, tree navigation, mobile navigation, and breadcrumbs.\n\n[Navigation category reference](https://github.com/janga/norna/blob/v0.7.22/docs/pages.md#navigation-categories)"
9
+ "markdownDescription": "```yaml\nlabel: Guides\n```\n\nThe category label shown in global navigation, tree navigation, mobile navigation, and breadcrumbs.\n\n[Navigation category reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation-categories)"
10
10
  }
11
11
  },
12
12
  "required": [
@@ -16,5 +16,5 @@
16
16
  "description": "A non-routable navigation category containing child pages.",
17
17
  "$id": "https://janga.github.io/norna/schemas/category.schema.json",
18
18
  "title": "Norna page category",
19
- "markdownDescription": "```yaml\nlabel: Guides\n```\n\n`category.yaml` creates a navigation-only group for child pages. It has no page content and produces no URL of its own.\n\n[Navigation category reference](https://github.com/janga/norna/blob/v0.7.22/docs/pages.md#navigation-categories)"
19
+ "markdownDescription": "```yaml\nlabel: Guides\n```\n\n`category.yaml` creates a navigation-only group for child pages. It has no page content and produces no URL of its own.\n\n[Navigation category reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation-categories)"
20
20
  }
@@ -6,7 +6,7 @@
6
6
  "type": "string",
7
7
  "format": "uri",
8
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.22/docs/configuration.md#url)",
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.23/docs/configuration.md#url)",
10
10
  "examples": [
11
11
  "https://example.com/",
12
12
  "https://owner.github.io/repository-name/"
@@ -27,12 +27,14 @@
27
27
  {
28
28
  "const": "en",
29
29
  "title": "English",
30
- "description": "Use Norna's built-in English interface text."
30
+ "description": "Use Norna's built-in English interface text.",
31
+ "markdownDescription": "Use Norna's built-in English interface text.\n\n[Language reference](https://github.com/janga/norna/blob/v0.7.23/docs/configuration.md#language)"
31
32
  },
32
33
  {
33
34
  "const": "sv",
34
35
  "title": "Swedish",
35
- "description": "Use Norna's built-in Swedish interface text."
36
+ "description": "Use Norna's built-in Swedish interface text.",
37
+ "markdownDescription": "Use Norna's built-in Swedish interface text.\n\n[Language reference](https://github.com/janga/norna/blob/v0.7.23/docs/configuration.md#language)"
36
38
  },
37
39
  {
38
40
  "type": "string",
@@ -41,7 +43,7 @@
41
43
  "description": "Use an English or Swedish regional language tag such as en-GB or sv-SE."
42
44
  }
43
45
  ],
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.22/docs/configuration.md#language)"
46
+ "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.23/docs/configuration.md#language)"
45
47
  },
46
48
  "navigation": {
47
49
  "type": "object",
@@ -53,46 +55,40 @@
53
55
  {
54
56
  "const": "automatic",
55
57
  "title": "Automatic",
56
- "description": "Choose sections for one page, top navigation for a shallow multi-page site, and tree navigation for deeper content."
58
+ "description": "Choose sections for one page, top navigation for Home and independent top-level pages, and tree navigation inside branches with listed children or categories.",
59
+ "markdownDescription": "Choose sections for one page, top navigation for Home and independent top-level pages, and tree navigation inside branches with listed children or categories.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)"
57
60
  },
58
61
  {
59
62
  "const": "sections",
60
63
  "title": "Sections",
61
- "description": "Navigate the sections of the current page."
64
+ "description": "Navigate the sections of the current page.",
65
+ "markdownDescription": "Navigate the sections of the current page.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)"
62
66
  },
63
67
  {
64
68
  "const": "top",
65
69
  "title": "Top",
66
- "description": "Use pages in the top navigation and sections below them."
70
+ "description": "Use pages in the top navigation and sections below them.",
71
+ "markdownDescription": "Use pages in the top navigation and sections below them.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)"
67
72
  },
68
73
  {
69
74
  "const": "tree",
70
75
  "title": "Tree",
71
- "description": "Use a hierarchical site-wide navigation tree."
76
+ "description": "Use a left page rail and a separate right H2/H3 contents rail where the page has enough headings.",
77
+ "markdownDescription": "Use a left page rail and a separate right H2/H3 contents rail where the page has enough headings.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)"
72
78
  }
73
79
  ],
74
- "markdownDescription": "```yaml\nnavigation:\n mode: automatic\n```\n\nNavigation model. Omit this to let Norna choose from the site structure.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/pages.md#navigation)",
80
+ "markdownDescription": "```yaml\nnavigation:\n mode: automatic\n```\n\nNavigation model. Omit this to let Norna choose from the site structure.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)",
75
81
  "examples": [
76
82
  "automatic",
77
83
  "sections",
78
84
  "top",
79
85
  "tree"
80
86
  ]
81
- },
82
- "sectionTracking": {
83
- "default": false,
84
- "description": "As the reader scrolls in tree navigation, mark the last H2 or H3 that has reached the reading area below the sticky header. The URL and keyboard focus do not change.",
85
- "type": "boolean",
86
- "markdownDescription": "```yaml\nnavigation:\n sectionTracking: true\n```\n\nAs the reader scrolls in tree navigation, mark the last H2 or H3 that has reached the reading area below the sticky header. The URL and keyboard focus do not change.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/configuration.md#navigationsectiontracking)",
87
- "examples": [
88
- true,
89
- false
90
- ]
91
87
  }
92
88
  },
93
89
  "additionalProperties": false,
94
90
  "description": "Site-wide navigation behavior.",
95
- "markdownDescription": "```yaml\nnavigation:\n mode: automatic\n```\n\nSets one navigation model for the complete site. `automatic` selects from the page hierarchy.\n\n[Navigation reference](https://github.com/janga/norna/blob/v0.7.22/docs/pages.md#navigation)"
91
+ "markdownDescription": "```yaml\nnavigation:\n mode: automatic\n```\n\nSets the site-wide navigation policy. `automatic` selects an effective mode for each page from its active top-level branch.\n\n[Navigation reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)"
96
92
  },
97
93
  "scrollBehavior": {
98
94
  "default": "instant",
@@ -102,15 +98,17 @@
102
98
  {
103
99
  "const": "instant",
104
100
  "title": "Instant",
105
- "description": "Jump directly to anchors without animated scrolling. This is the default."
101
+ "description": "Jump directly to anchors without animated scrolling. This is the default.",
102
+ "markdownDescription": "Jump directly to anchors without animated scrolling. This is the default.\n\n[Scroll behavior reference](https://github.com/janga/norna/blob/v0.7.23/docs/configuration.md#scrollbehavior)"
106
103
  },
107
104
  {
108
105
  "const": "smooth",
109
106
  "title": "Browser smooth",
110
- "description": "Use the browser's native smooth scrolling for anchor navigation."
107
+ "description": "Use the browser's native smooth scrolling for anchor navigation.",
108
+ "markdownDescription": "Use the browser's native smooth scrolling for anchor navigation.\n\n[Scroll behavior reference](https://github.com/janga/norna/blob/v0.7.23/docs/configuration.md#scrollbehavior)"
111
109
  }
112
110
  ],
113
- "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.22/docs/configuration.md#scrollbehavior)",
111
+ "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.23/docs/configuration.md#scrollbehavior)",
114
112
  "examples": [
115
113
  "instant",
116
114
  "smooth"
@@ -124,5 +122,5 @@
124
122
  "description": "Technical settings for one Norna site. Additional pages cannot provide technical configuration.",
125
123
  "$id": "https://janga.github.io/norna/schemas/config.schema.json",
126
124
  "title": "Norna site configuration",
127
- "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.22/docs/configuration.md)"
125
+ "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.23/docs/configuration.md)"
128
126
  }
@@ -9,15 +9,35 @@
9
9
  "description": "Optional page-specific meta description.",
10
10
  "type": "string",
11
11
  "minLength": 1,
12
- "markdownDescription": "```yaml\npage:\n description: About this project.\n```\n\nAn optional page-specific description rendered as `<meta name=\"description\">`. It is not visible in page content.\n\n[Page title and frontmatter reference](https://github.com/janga/norna/blob/v0.7.22/docs/content.md#page-title-and-frontmatter)",
12
+ "markdownDescription": "```yaml\npage:\n description: About this project.\n```\n\nAn optional page-specific description rendered as `<meta name=\"description\">`. It is not visible in page content.\n\n[Page title and frontmatter reference](https://github.com/janga/norna/blob/v0.7.23/docs/content.md#page-title-and-frontmatter)",
13
13
  "examples": [
14
14
  "About this project."
15
15
  ]
16
+ },
17
+ "aliases": {
18
+ "description": "Previous site-relative URLs that permanently identify this page. The current page is always the target.",
19
+ "minItems": 1,
20
+ "type": "array",
21
+ "items": {
22
+ "type": "string",
23
+ "pattern": "^\\/(?:[a-z0-9]+(?:-[a-z0-9]+)*\\/)+$",
24
+ "description": "Previous site-relative URL that permanently identifies this page.",
25
+ "markdownDescription": "```yaml\npage:\n aliases:\n - /old-about/\n```\n\nUse a previous Norna page URL. Start and end with `/`; use lowercase ASCII letters, numbers, and single hyphens; do not include the configured base path, a query string, or a fragment.\n\n[Alias path rules](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#preserve-old-page-urls)",
26
+ "examples": [
27
+ "/old-about/"
28
+ ]
29
+ },
30
+ "markdownDescription": "```yaml\npage:\n aliases:\n - /old-about/\n```\n\nLists previous site-relative URLs that permanently identify this page. The page containing the list is always the target. Paths omit the configured base path and are excluded from the sitemap.\n\n[Preserve old page URLs](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#preserve-old-page-urls)",
31
+ "examples": [
32
+ [
33
+ "/old-about/"
34
+ ]
35
+ ]
16
36
  }
17
37
  },
18
38
  "additionalProperties": false,
19
39
  "description": "Optional metadata for this homepage or additional page. The Markdown H1 supplies the page title.",
20
- "markdownDescription": "```yaml\npage:\n description: About this project.\n```\n\nContains optional metadata for the current homepage or additional page. The Markdown H1 supplies its title.\n\n[Page title and frontmatter reference](https://github.com/janga/norna/blob/v0.7.22/docs/content.md#page-title-and-frontmatter)"
40
+ "markdownDescription": "```yaml\npage:\n description: About this project.\n aliases:\n - /old-about/\n```\n\nContains optional metadata for the current homepage or additional page. The Markdown H1 supplies its title. An alias records an old URL for this same page.\n\n[Page title and frontmatter reference](https://github.com/janga/norna/blob/v0.7.23/docs/content.md#page-title-and-frontmatter)"
21
41
  },
22
42
  "navigation": {
23
43
  "description": "Optional navigation metadata for this page.",
@@ -27,7 +47,7 @@
27
47
  "default": true,
28
48
  "description": "List this page in site navigation. The page remains public when false.",
29
49
  "type": "boolean",
30
- "markdownDescription": "```yaml\nnavigation:\n listed: false\n```\n\nList this page in site navigation. The page remains public when false.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/pages.md#navigation)",
50
+ "markdownDescription": "```yaml\nnavigation:\n listed: false\n```\n\nList this page in site navigation. The page remains public when false.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)",
31
51
  "examples": [
32
52
  true,
33
53
  false
@@ -35,12 +55,12 @@
35
55
  }
36
56
  },
37
57
  "additionalProperties": false,
38
- "markdownDescription": "```yaml\nnavigation:\n listed: false\n```\n\nOptionally excludes an additional page from site navigation without removing its public URL.\n\n[Site navigation reference](https://github.com/janga/norna/blob/v0.7.22/docs/pages.md#navigation)"
58
+ "markdownDescription": "```yaml\nnavigation:\n listed: false\n```\n\nOptionally excludes an additional page from site navigation without removing its public URL.\n\n[Site navigation reference](https://github.com/janga/norna/blob/v0.7.23/docs/pages.md#navigation)"
39
59
  }
40
60
  },
41
61
  "additionalProperties": false,
42
62
  "description": "Frontmatter for a homepage or additional page content.md file.",
43
63
  "$id": "https://janga.github.io/norna/schemas/content-frontmatter.schema.json",
44
64
  "title": "Norna page frontmatter",
45
- "markdownDescription": "```yaml\n---\npage:\n description: About this project.\n---\n```\n\nContent frontmatter is optional. Write the page title as the single Markdown H1; use frontmatter only for optional metadata or navigation settings.\n\n[Page title and frontmatter reference](https://github.com/janga/norna/blob/v0.7.22/docs/content.md#page-title-and-frontmatter)"
65
+ "markdownDescription": "```yaml\n---\npage:\n description: About this project.\n---\n```\n\nContent frontmatter is optional. Write the page title as the single Markdown H1; use frontmatter only for optional metadata or navigation settings.\n\n[Page title and frontmatter reference](https://github.com/janga/norna/blob/v0.7.23/docs/content.md#page-title-and-frontmatter)"
46
66
  }
@@ -12,20 +12,23 @@
12
12
  {
13
13
  "const": "compact",
14
14
  "title": "Compact",
15
- "description": "Use restrained spacing between sections and structured blocks."
15
+ "description": "Use restrained spacing between sections and structured blocks.",
16
+ "markdownDescription": "Use restrained spacing between sections and structured blocks.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
16
17
  },
17
18
  {
18
19
  "const": "normal",
19
20
  "title": "Normal",
20
- "description": "Use balanced content spacing."
21
+ "description": "Use balanced content spacing.",
22
+ "markdownDescription": "Use balanced content spacing.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
21
23
  },
22
24
  {
23
25
  "const": "spacious",
24
26
  "title": "Spacious",
25
- "description": "Use more expansive spacing between sections and structured blocks."
27
+ "description": "Use more expansive spacing between sections and structured blocks.",
28
+ "markdownDescription": "Use more expansive spacing between sections and structured blocks.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
26
29
  }
27
30
  ],
28
- "markdownDescription": "```yaml\nlayout:\n contentSpacing: compact\n```\n\nPage content spacing. Descendant pages inherit this value.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#page-themes)",
31
+ "markdownDescription": "```yaml\nlayout:\n contentSpacing: compact\n```\n\nPage content spacing. Descendant pages inherit this value.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)",
29
32
  "examples": [
30
33
  "compact",
31
34
  "normal",
@@ -39,20 +42,23 @@
39
42
  {
40
43
  "const": "narrow",
41
44
  "title": "Narrow",
42
- "description": "Use a shorter line length suited to reading-focused text."
45
+ "description": "Use a shorter line length suited to reading-focused text.",
46
+ "markdownDescription": "Use a shorter line length suited to reading-focused text.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
43
47
  },
44
48
  {
45
49
  "const": "normal",
46
50
  "title": "Normal",
47
- "description": "Use the balanced default line length."
51
+ "description": "Use the balanced default line length.",
52
+ "markdownDescription": "Use the balanced default line length.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
48
53
  },
49
54
  {
50
55
  "const": "wide",
51
56
  "title": "Wide",
52
- "description": "Allow body text to use more horizontal space."
57
+ "description": "Allow body text to use more horizontal space.",
58
+ "markdownDescription": "Allow body text to use more horizontal space.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
53
59
  }
54
60
  ],
55
- "markdownDescription": "```yaml\nlayout:\n textWidth: narrow\n```\n\nBody-text line length. Descendant pages inherit this value.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#page-themes)",
61
+ "markdownDescription": "```yaml\nlayout:\n textWidth: narrow\n```\n\nBody-text line length. Descendant pages inherit this value.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)",
56
62
  "examples": [
57
63
  "narrow",
58
64
  "normal",
@@ -62,16 +68,35 @@
62
68
  },
63
69
  "additionalProperties": false,
64
70
  "description": "Page-local layout settings inherited by descendant pages.",
65
- "markdownDescription": "```yaml\nlayout:\n textWidth: narrow\n contentSpacing: compact\n```\n\nAdjusts body-text line length and vertical content spacing for pages below this directory.\n\n[Page theme reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#page-themes)"
71
+ "markdownDescription": "```yaml\nlayout:\n textWidth: narrow\n contentSpacing: compact\n```\n\nAdjusts body-text line length and vertical content spacing for pages below this directory.\n\n[Page theme reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
66
72
  },
67
73
  "images": {
68
74
  "type": "object",
69
75
  "properties": {
76
+ "presentation": {
77
+ "description": "Managed-image presentation method. Omit this to keep the selected preset or inherited page setting.",
78
+ "type": "string",
79
+ "oneOf": [
80
+ {
81
+ "const": "prose-aligned",
82
+ "title": "Prose-aligned",
83
+ "description": "Start managed images and captions at the body-text edge and size them from the page content area.",
84
+ "markdownDescription": "Start managed images and captions at the body-text edge and size them from the page content area.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
85
+ },
86
+ {
87
+ "const": "centered-fit",
88
+ "title": "Centered fit",
89
+ "description": "Center managed images and captions in the page media area and constrain them by available width and viewport height.",
90
+ "markdownDescription": "Center managed images and captions in the page media area and constrain them by available width and viewport height.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
91
+ }
92
+ ],
93
+ "markdownDescription": "```yaml\nimages:\n presentation: prose-aligned\n```\n\nManaged-image presentation method. Omit this to keep the selected preset or inherited page setting.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
94
+ },
70
95
  "width": {
71
96
  "description": "Maximum managed-image width. Omit this to keep the selected preset.",
72
97
  "type": "string",
73
98
  "pattern": "^(?:0|(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)|clamp\\(\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*,\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*,\\s*(?:\\d+(?:\\.\\d+)?|\\.\\d+)(?:px|rem|em|vw|vh|vmin|vmax|ch|%)\\s*\\))$",
74
- "markdownDescription": "```yaml\nimages:\n width: 900px\n```\n\nMaximum managed-image width. Omit this to keep the selected preset.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
99
+ "markdownDescription": "```yaml\nimages:\n width: 900px\n```\n\nMaximum managed-image width. Omit this to keep the selected preset.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
75
100
  },
76
101
  "maxAvailableWidthPercent": {
77
102
  "description": "Maximum percentage of available horizontal space used by managed images.",
@@ -89,14 +114,14 @@
89
114
  "exclusiveMinimum": 0,
90
115
  "maximum": 100,
91
116
  "description": "Percentage used on wider screens.",
92
- "markdownDescription": "```yaml\nimages:\n maxAvailableWidthPercent:\n desktop: 100\n```\n\nPercentage used on wider screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
117
+ "markdownDescription": "```yaml\nimages:\n maxAvailableWidthPercent:\n desktop: 100\n```\n\nPercentage used on wider screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
93
118
  },
94
119
  "mobile": {
95
120
  "type": "number",
96
121
  "exclusiveMinimum": 0,
97
122
  "maximum": 100,
98
123
  "description": "Percentage used on narrow screens.",
99
- "markdownDescription": "```yaml\nimages:\n maxAvailableWidthPercent:\n mobile: 100\n```\n\nPercentage used on narrow screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
124
+ "markdownDescription": "```yaml\nimages:\n maxAvailableWidthPercent:\n mobile: 100\n```\n\nPercentage used on narrow screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
100
125
  }
101
126
  },
102
127
  "required": [
@@ -106,10 +131,10 @@
106
131
  "additionalProperties": false
107
132
  }
108
133
  ],
109
- "markdownDescription": "```yaml\nimages:\n maxAvailableWidthPercent:\n desktop: 100\n mobile: 100\n```\n\nMaximum percentage of available horizontal space used by managed images.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
134
+ "markdownDescription": "```yaml\nimages:\n maxAvailableWidthPercent:\n desktop: 100\n mobile: 100\n```\n\nMaximum percentage of available horizontal space used by managed images.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
110
135
  },
111
136
  "maxAvailableHeightPercent": {
112
- "description": "Maximum percentage of viewport height used by managed images.",
137
+ "description": "Maximum percentage of viewport height used by centered-fit images. This setting is unavailable with prose-aligned presentation.",
113
138
  "anyOf": [
114
139
  {
115
140
  "type": "number",
@@ -124,14 +149,14 @@
124
149
  "exclusiveMinimum": 0,
125
150
  "maximum": 100,
126
151
  "description": "Percentage used on wider screens.",
127
- "markdownDescription": "```yaml\nimages:\n maxAvailableHeightPercent:\n desktop: 74\n```\n\nPercentage used on wider screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
152
+ "markdownDescription": "```yaml\nimages:\n maxAvailableHeightPercent:\n desktop: 74\n```\n\nPercentage used on wider screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
128
153
  },
129
154
  "mobile": {
130
155
  "type": "number",
131
156
  "exclusiveMinimum": 0,
132
157
  "maximum": 100,
133
158
  "description": "Percentage used on narrow screens.",
134
- "markdownDescription": "```yaml\nimages:\n maxAvailableHeightPercent:\n mobile: 68\n```\n\nPercentage used on narrow screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
159
+ "markdownDescription": "```yaml\nimages:\n maxAvailableHeightPercent:\n mobile: 68\n```\n\nPercentage used on narrow screens.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
135
160
  }
136
161
  },
137
162
  "required": [
@@ -141,12 +166,12 @@
141
166
  "additionalProperties": false
142
167
  }
143
168
  ],
144
- "markdownDescription": "```yaml\nimages:\n maxAvailableHeightPercent:\n desktop: 74\n mobile: 68\n```\n\nMaximum percentage of viewport height used by managed images.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
169
+ "markdownDescription": "```yaml\nimages:\n maxAvailableHeightPercent:\n desktop: 74\n mobile: 68\n```\n\nMaximum percentage of viewport height used by centered-fit images. This setting is unavailable with prose-aligned presentation.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
145
170
  }
146
171
  },
147
172
  "additionalProperties": false,
148
- "description": "Optional defaults for managed image presentation.",
149
- "markdownDescription": "```yaml\nimages:\n width: 900px\n```\n\nAdjusts managed-image sizing for pages below this directory.\n\n[Image sizing reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#image-sizing)"
173
+ "description": "Optional defaults for placing managed images inside the page content area. Persistent navigation remains outside this area.",
174
+ "markdownDescription": "```yaml\nimages:\n presentation: prose-aligned\n width: 900px\n```\n\nAdjusts managed-image presentation and sizing inside the content area for pages below this directory. Persistent navigation remains outside this area.\n\n[Image sizing reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#image-sizing)"
150
175
  },
151
176
  "sections": {
152
177
  "type": "object",
@@ -158,20 +183,23 @@
158
183
  {
159
184
  "const": "uniform",
160
185
  "title": "Uniform",
161
- "description": "Use the normal page background for every H2 section. Tree navigation requires this pattern."
186
+ "description": "Use the normal page background for every H2 section. Tree navigation requires this pattern.",
187
+ "markdownDescription": "Use the normal page background for every H2 section. Tree navigation requires this pattern.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
162
188
  },
163
189
  {
164
190
  "const": "alternating",
165
191
  "title": "Alternating",
166
- "description": "Alternate normal and subtly contrasting full-width section backgrounds. Available with sections and top navigation."
192
+ "description": "Alternate normal and subtly contrasting full-width section backgrounds. Available with sections and top navigation.",
193
+ "markdownDescription": "Alternate normal and subtly contrasting full-width section backgrounds. Available with sections and top navigation.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
167
194
  },
168
195
  {
169
196
  "const": "accented",
170
197
  "title": "Accented",
171
- "description": "Move through base, soft, emphasis and soft full-width section backgrounds before repeating. Available with sections and top navigation."
198
+ "description": "Move through base, soft, emphasis and soft full-width section backgrounds before repeating. Available with sections and top navigation.",
199
+ "markdownDescription": "Move through base, soft, emphasis and soft full-width section backgrounds before repeating. Available with sections and top navigation.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
172
200
  }
173
201
  ],
174
- "markdownDescription": "```yaml\nsections:\n backgroundPattern: alternating\n```\n\nSection background sequence inherited by descendant pages. Non-uniform patterns are invalid with tree navigation.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#page-themes)",
202
+ "markdownDescription": "```yaml\nsections:\n backgroundPattern: alternating\n```\n\nSection background sequence inherited by descendant pages. Non-uniform patterns are invalid with tree navigation.\n\n[Read the relevant reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)",
175
203
  "examples": [
176
204
  "uniform",
177
205
  "alternating",
@@ -181,12 +209,12 @@
181
209
  },
182
210
  "additionalProperties": false,
183
211
  "description": "Page-local section presentation inherited by descendant pages.",
184
- "markdownDescription": "```yaml\nsections:\n backgroundPattern: alternating\n```\n\nAdjusts 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.\n\n[Page theme reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#page-themes)"
212
+ "markdownDescription": "```yaml\nsections:\n backgroundPattern: alternating\n```\n\nAdjusts 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.\n\n[Page theme reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
185
213
  }
186
214
  },
187
215
  "additionalProperties": false,
188
216
  "description": "Limited page presentation overrides inherited by descendant pages. Site colors, corners, typography, content-block defaults and navigation remain global.",
189
217
  "$id": "https://janga.github.io/norna/schemas/page-theme.schema.json",
190
218
  "title": "Norna page theme",
191
- "markdownDescription": "```yaml\nlayout:\n textWidth: narrow\n contentSpacing: compact\n```\n\nA 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.\n\n[Page theme reference](https://github.com/janga/norna/blob/v0.7.22/docs/theme.md#page-themes)"
219
+ "markdownDescription": "```yaml\nlayout:\n textWidth: narrow\n contentSpacing: compact\n```\n\nA 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.\n\n[Page theme reference](https://github.com/janga/norna/blob/v0.7.23/docs/theme.md#page-themes)"
192
220
  }