@janga/norna 0.7.24 → 0.7.26

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 (142) hide show
  1. package/README.md +5 -4
  2. package/astro.config.mjs +27 -11
  3. package/bin/norna-cli.mjs +12 -0
  4. package/package.json +26 -5
  5. package/schemas/card-list.schema.json +121 -0
  6. package/schemas/category.schema.json +2 -2
  7. package/schemas/config.schema.json +342 -33
  8. package/schemas/content-frontmatter.schema.json +7 -7
  9. package/schemas/image-carousel.schema.json +43 -0
  10. package/schemas/image-stack.schema.json +43 -0
  11. package/schemas/manifest.json +6 -1
  12. package/schemas/page-theme.schema.json +26 -26
  13. package/schemas/sitewide-content.schema.json +18 -18
  14. package/schemas/theme.schema.json +237 -262
  15. package/scripts/check-config.mjs +5 -1
  16. package/scripts/dev-local.mjs +130 -13
  17. package/scripts/generate-schemas.mjs +15 -3
  18. package/scripts/init-site.mjs +2 -0
  19. package/scripts/lib/category-destinations.mjs +48 -0
  20. package/scripts/lib/code-fence-metadata.mjs +25 -43
  21. package/scripts/lib/content-tabs.mjs +155 -0
  22. package/scripts/lib/details-headings.mjs +58 -0
  23. package/scripts/lib/docusaurus-migration-audit.mjs +603 -0
  24. package/scripts/lib/edit-source-link.mjs +53 -0
  25. package/scripts/lib/editor-language-service.mjs +238 -116
  26. package/scripts/lib/locale-registry.mjs +597 -0
  27. package/scripts/lib/locales/az-Latn.mjs +78 -0
  28. package/scripts/lib/locales/be.mjs +78 -0
  29. package/scripts/lib/locales/bg.mjs +78 -0
  30. package/scripts/lib/locales/bs.mjs +78 -0
  31. package/scripts/lib/locales/ca.mjs +78 -0
  32. package/scripts/lib/locales/cnr.mjs +78 -0
  33. package/scripts/lib/locales/cs.mjs +78 -0
  34. package/scripts/lib/locales/da.mjs +78 -0
  35. package/scripts/lib/locales/de.mjs +78 -0
  36. package/scripts/lib/locales/el.mjs +78 -0
  37. package/scripts/lib/locales/en.mjs +78 -0
  38. package/scripts/lib/locales/es.mjs +78 -0
  39. package/scripts/lib/locales/et.mjs +78 -0
  40. package/scripts/lib/locales/fi.mjs +78 -0
  41. package/scripts/lib/locales/fil.mjs +78 -0
  42. package/scripts/lib/locales/fr.mjs +78 -0
  43. package/scripts/lib/locales/ga.mjs +78 -0
  44. package/scripts/lib/locales/ha.mjs +78 -0
  45. package/scripts/lib/locales/hr.mjs +78 -0
  46. package/scripts/lib/locales/hu.mjs +78 -0
  47. package/scripts/lib/locales/id.mjs +78 -0
  48. package/scripts/lib/locales/is.mjs +78 -0
  49. package/scripts/lib/locales/it.mjs +78 -0
  50. package/scripts/lib/locales/jv.mjs +78 -0
  51. package/scripts/lib/locales/lb.mjs +78 -0
  52. package/scripts/lib/locales/lt.mjs +78 -0
  53. package/scripts/lib/locales/lv.mjs +78 -0
  54. package/scripts/lib/locales/mk.mjs +78 -0
  55. package/scripts/lib/locales/mt.mjs +78 -0
  56. package/scripts/lib/locales/nb.mjs +78 -0
  57. package/scripts/lib/locales/nl.mjs +78 -0
  58. package/scripts/lib/locales/nn.mjs +78 -0
  59. package/scripts/lib/locales/pcm.mjs +78 -0
  60. package/scripts/lib/locales/pl.mjs +78 -0
  61. package/scripts/lib/locales/pt.mjs +78 -0
  62. package/scripts/lib/locales/ro.mjs +78 -0
  63. package/scripts/lib/locales/ru.mjs +78 -0
  64. package/scripts/lib/locales/sk.mjs +78 -0
  65. package/scripts/lib/locales/sl.mjs +78 -0
  66. package/scripts/lib/locales/sq.mjs +78 -0
  67. package/scripts/lib/locales/sr-Cyrl.mjs +78 -0
  68. package/scripts/lib/locales/sr-Latn.mjs +78 -0
  69. package/scripts/lib/locales/sv.mjs +78 -0
  70. package/scripts/lib/locales/sw.mjs +78 -0
  71. package/scripts/lib/locales/tr.mjs +78 -0
  72. package/scripts/lib/locales/uk.mjs +78 -0
  73. package/scripts/lib/locales/vi.mjs +78 -0
  74. package/scripts/lib/markdown-links.mjs +4 -25
  75. package/scripts/lib/markdown-notes-render-plugin.mjs +75 -0
  76. package/scripts/lib/markdown-notes.mjs +165 -0
  77. package/scripts/lib/navigation-model.mjs +1 -1
  78. package/scripts/lib/norna-markdown-blocks.mjs +123 -447
  79. package/scripts/lib/norna-markdown-render-plugin.mjs +4 -0
  80. package/scripts/lib/page-aliases.mjs +12 -1
  81. package/scripts/lib/page-markdown.mjs +63 -16
  82. package/scripts/lib/page-move-plan.mjs +22 -5
  83. package/scripts/lib/pagefind-translations.mjs +620 -0
  84. package/scripts/lib/presentation-contract.mjs +6 -1
  85. package/scripts/lib/presentation.mjs +29 -30
  86. package/scripts/lib/project-config.mjs +22 -163
  87. package/scripts/lib/schema-definitions.mjs +13 -12
  88. package/scripts/lib/schema-editor-metadata.mjs +42 -46
  89. package/scripts/lib/schema-value-definitions.mjs +7 -8
  90. package/scripts/lib/semantic-callouts.mjs +4 -2
  91. package/scripts/lib/site-content.mjs +4 -2
  92. package/scripts/lib/site-link-graph.mjs +16 -6
  93. package/scripts/lib/site-navigation-tree.mjs +0 -11
  94. package/scripts/lib/site-paths.mjs +14 -2
  95. package/scripts/lib/sitemap.mjs +5 -3
  96. package/scripts/lib/structured-blocks.mjs +108 -0
  97. package/scripts/lib/table-render-plugin.mjs +76 -0
  98. package/scripts/lib/table-row-headers.mjs +218 -0
  99. package/scripts/lib/theme-presets.mjs +3 -10
  100. package/scripts/lib/yaml-config.mjs +2 -6
  101. package/scripts/migrate-check.mjs +19 -0
  102. package/scripts/sync-content-sections.mjs +39 -10
  103. package/scripts/sync-site-public.mjs +7 -1
  104. package/src/components/CardList.astro +1 -0
  105. package/src/components/CodeBlockCopyScript.astro +49 -6
  106. package/src/components/ContentBlocks.astro +39 -0
  107. package/src/components/ContentTabsScript.astro +60 -0
  108. package/src/components/DisplaySettings.astro +17 -19
  109. package/src/components/ImageCarousel.astro +4 -1
  110. package/src/components/ImageStack.astro +34 -9
  111. package/src/components/ImageStackEnhancement.astro +331 -0
  112. package/src/components/NavigationPageTree.astro +1 -1
  113. package/src/components/NoteNavigationScript.astro +4 -0
  114. package/src/components/PageAliasRedirect.astro +5 -4
  115. package/src/components/PageContentsNavigation.astro +2 -3
  116. package/src/components/SearchNavigationScript.astro +4 -0
  117. package/src/components/SearchPage.astro +43 -2
  118. package/src/components/SectionNavigationScript.astro +86 -16
  119. package/src/components/SiteBreadcrumbs.astro +1 -1
  120. package/src/components/SiteNavigation.astro +98 -65
  121. package/src/components/SitePage.astro +73 -33
  122. package/src/components/SiteSection.astro +5 -81
  123. package/src/components/SiteTreeNavigation.astro +5 -2
  124. package/src/components/TableOverflowScript.astro +579 -0
  125. package/src/components/TopPageMenu.astro +47 -0
  126. package/src/components/TreeNavigationScript.astro +86 -23
  127. package/src/layouts/BaseLayout.astro +34 -12
  128. package/src/lib/generatedImages.ts +18 -0
  129. package/src/lib/navigationFollowing.ts +142 -0
  130. package/src/lib/noteNavigation.ts +50 -0
  131. package/src/lib/searchNavigation.ts +107 -0
  132. package/src/lib/sectionContent.ts +23 -116
  133. package/src/lib/siteNavigation.ts +0 -5
  134. package/src/lib/sitePages.ts +18 -4
  135. package/src/lib/table-sort-tooltip.ts +109 -0
  136. package/src/pages/[...slug].astro +16 -6
  137. package/src/styles/content.css +563 -26
  138. package/src/styles/foundations.css +9 -0
  139. package/src/styles/media.css +192 -3
  140. package/src/styles/navigation.css +214 -60
  141. package/src/styles/page-layout.css +55 -16
  142. package/src/styles/responsive.css +62 -20
package/README.md CHANGED
@@ -71,13 +71,14 @@ site/
71
71
  a routable page or `category.yaml` for a navigation-only group.
72
72
  - A page may contain local images. A page or category may contain limited
73
73
  presentation settings and nested entries under its own `pages/` directory.
74
- - Category ids remain in child URLs, but categories do not generate pages of
75
- their own.
74
+ - Category ids remain in child URLs. Opening a category URL leads to its first
75
+ listed direct page or a generated child list; see
76
+ [Category destinations](docs/pages.md#opening-a-category-url).
76
77
  - `theme.yaml` normally selects one complete visual preset.
77
78
  - `sitewide-content.yaml` holds shared logo display settings, banners, and
78
79
  footer content.
79
- - `config.yaml` holds the public URL and optional language, source edit link,
80
- navigation model, static search, and scroll behavior.
80
+ - `config.yaml` holds the public URL and optional language, local and remote
81
+ source links, navigation model, static search, and scroll behavior.
81
82
  - `public/` holds static files copied without processing.
82
83
 
83
84
  Norna validates this structure, processes managed images when needed, and
package/astro.config.mjs CHANGED
@@ -4,9 +4,12 @@ import path from 'node:path';
4
4
  import { promisify } from 'node:util';
5
5
  import { defineConfig } from 'astro/config';
6
6
  import { satteri } from '@astrojs/markdown-satteri';
7
+ import { prepareContentTabs } from './scripts/lib/content-tabs.mjs';
7
8
  import { getBasePathRedirectLocation } from './scripts/lib/base-path-redirect.mjs';
8
9
  import { nornaCodeFenceTransformer } from './scripts/lib/code-fence-metadata.mjs';
9
10
  import { nornaMarkdownRenderPlugin } from './scripts/lib/norna-markdown-render-plugin.mjs';
11
+ import { nornaNotesRenderPlugin } from './scripts/lib/markdown-notes-render-plugin.mjs';
12
+ import { nornaTableRenderPlugin } from './scripts/lib/table-render-plugin.mjs';
10
13
  import {
11
14
  astroCacheDir,
12
15
  astroDistDir,
@@ -132,6 +135,29 @@ const nornaGeneratedImagesWatcher = () => ({
132
135
  },
133
136
  });
134
137
 
138
+ const markdownProcessor = satteri({
139
+ features: {
140
+ gfm: { footnotes: {
141
+ label: projectConfig.locale.labels.footnotes,
142
+ backLabel: projectConfig.locale.labels.footnoteBackReference,
143
+ } },
144
+ },
145
+ mdastPlugins: [nornaNotesRenderPlugin, nornaMarkdownRenderPlugin],
146
+ hastPlugins: [nornaTableRenderPlugin],
147
+ });
148
+ const createMarkdownRenderer = markdownProcessor.createRenderer.bind(markdownProcessor);
149
+ markdownProcessor.createRenderer = async (shared) => {
150
+ const renderer = await createMarkdownRenderer(shared);
151
+ return {
152
+ ...renderer,
153
+ render(source, options) {
154
+ return renderer.render(prepareContentTabs(source, {
155
+ label: options?.fileURL?.pathname ?? 'Markdown',
156
+ }), options);
157
+ },
158
+ };
159
+ };
160
+
135
161
  // https://astro.build/config
136
162
  export default defineConfig({
137
163
  base: projectConfig.site.basePath,
@@ -140,17 +166,7 @@ export default defineConfig({
140
166
  shikiConfig: {
141
167
  transformers: [nornaCodeFenceTransformer],
142
168
  },
143
- processor: satteri({
144
- features: {
145
- gfm: {
146
- footnotes: {
147
- label: projectConfig.locale.labels.footnotes,
148
- backLabel: projectConfig.locale.labels.footnoteBackReference,
149
- },
150
- },
151
- },
152
- mdastPlugins: [nornaMarkdownRenderPlugin],
153
- }),
169
+ processor: markdownProcessor,
154
170
  },
155
171
  outDir: astroDistDir,
156
172
  publicDir: astroPublicDir,
package/bin/norna-cli.mjs CHANGED
@@ -31,6 +31,7 @@ Commands:
31
31
  page:add Add a page to the site page tree
32
32
  page:move Move a page subtree and update internal links
33
33
  category:add Add a non-routable category to the site page tree
34
+ migrate:check Audit a Docusaurus project without modifying it
34
35
  build Build the selected site
35
36
  build:local Build and restart local dev server
36
37
  deploy Build and deploy committed branch
@@ -100,6 +101,17 @@ if (command === '-h' || command === '--help' || command === 'help') {
100
101
  process.exit(0);
101
102
  }
102
103
 
104
+ if (command === 'migrate:check') {
105
+ try {
106
+ process.argv = [process.argv[0], process.argv[1], ...rest];
107
+ await import('../scripts/migrate-check.mjs');
108
+ } catch (error) {
109
+ console.error(error instanceof Error ? error.message : String(error));
110
+ process.exit(1);
111
+ }
112
+ process.exit(0);
113
+ }
114
+
103
115
  const [
104
116
  { runAstroInherit },
105
117
  { engineRoot, siteProjectRoot },
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.24",
5
+ "version": "0.7.26",
6
6
  "license": "GPL-3.0-only",
7
7
  "repository": {
8
8
  "type": "git",
@@ -44,6 +44,7 @@
44
44
  "scripts/generate-schemas.mjs",
45
45
  "scripts/generate-search-index.mjs",
46
46
  "scripts/init-site.mjs",
47
+ "scripts/migrate-check.mjs",
47
48
  "scripts/lib/",
48
49
  "!scripts/lib/documentation-preset-candidates.mjs",
49
50
  "!scripts/lib/example-sites.mjs",
@@ -72,6 +73,13 @@
72
73
  "dev:status": "node bin/norna.mjs dev:status",
73
74
  "dev:logs": "node bin/norna.mjs dev:logs",
74
75
  "dev:stop": "node bin/norna.mjs dev:stop",
76
+ "review:start": "node scripts/review-environments.mjs start",
77
+ "review:status": "node scripts/review-environments.mjs status",
78
+ "review:logs": "node scripts/review-environments.mjs logs",
79
+ "review:stop": "node scripts/review-environments.mjs stop",
80
+ "review:test": "node scripts/review-environments.mjs test",
81
+ "review:capture": "node scripts/review-environments.mjs capture",
82
+ "review:scratch": "node scripts/review-environments.mjs scratch",
75
83
  "config:check": "node bin/norna.mjs config:check",
76
84
  "content:check": "node bin/norna.mjs content:check",
77
85
  "content:sync": "node bin/norna.mjs content:sync",
@@ -92,11 +100,13 @@
92
100
  "deploy:watch": "node bin/norna.mjs deploy:watch",
93
101
  "doctor": "node bin/norna.mjs doctor",
94
102
  "demo:build": "node scripts/build-demo.mjs",
95
- "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:not-found-page && npm run test:site-node-commands && npm run test:page-move && npm run test:navigation-review && npm run test:nested-pages && npm run test:heading-ids && npm run test:navigation-model && npm run test:project-config && npm run test:edit-source-link && npm run test:static-search && 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",
103
+ "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:migration-check && npm run test:site-links && npm run test:page-aliases && npm run test:sitemap && npm run test:not-found-page && npm run test:site-node-commands && npm run test:page-move && npm run test:navigation-review && npm run test:nested-pages && npm run test:heading-ids && npm run test:navigation-model && npm run test:project-config && npm run test:locales && npm run test:edit-source-link && npm run test:static-search && 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:presentation-review && 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:review-environments && 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:table-sorting && npm run test:fixture:build && npm run test:examples && npm run package:check",
96
104
  "test:fixture:build": "node scripts/test-basic-fixture-build.mjs",
97
105
  "test:examples": "node scripts/test-examples.mjs",
106
+ "test:examples:browser": "node scripts/test-navigation.mjs --site-dir site tests/examples-gallery.spec.ts",
98
107
  "test:page-model": "node scripts/test-page-model.mjs",
99
- "test:page-markdown": "node scripts/test-page-markdown.mjs",
108
+ "test:page-markdown": "node scripts/test-page-markdown.mjs && node scripts/test-structured-blocks.mjs && node scripts/test-named-notes.mjs && node scripts/test-content-tabs.mjs",
109
+ "test:tabs:browser": "node scripts/test-navigation.mjs --site-dir fixtures/content-tabs/site tests/content-tabs.spec.ts",
100
110
  "test:site-links": "node scripts/test-site-link-graph.mjs",
101
111
  "test:page-aliases": "node scripts/test-page-aliases.mjs",
102
112
  "test:sitemap": "node scripts/test-sitemap.mjs",
@@ -104,13 +114,15 @@
104
114
  "test:site-node-commands": "node scripts/test-site-node-commands.mjs",
105
115
  "test:page-move": "node scripts/test-page-move.mjs",
106
116
  "test:navigation-review": "node scripts/test-navigation-review.mjs",
107
- "test:nested-pages": "node scripts/test-nested-pages.mjs",
117
+ "test:nested-pages": "node scripts/test-nested-pages.mjs && node scripts/test-top-navigation-contract.mjs",
108
118
  "test:heading-ids": "node scripts/test-heading-ids.mjs",
109
119
  "test:navigation-model": "node scripts/test-navigation-model.mjs",
110
120
  "test:schemas": "node scripts/test-schemas.mjs",
111
121
  "test:project-config": "node scripts/test-project-config.mjs",
122
+ "test:locales": "node scripts/test-locales.mjs",
112
123
  "test:edit-source-link": "node scripts/test-edit-source-link.mjs",
113
124
  "test:static-search": "node scripts/test-static-search.mjs",
125
+ "test:search:browser": "node scripts/test-navigation.mjs --site-dir site tests/search-navigation.spec.ts",
114
126
  "test:content-check": "node scripts/test-content-check.mjs",
115
127
  "test:content-sync-plan": "node scripts/test-content-sync-plan.mjs",
116
128
  "test:content-model": "npm run test:page-content && npm run test:managed-media && npm run test:content-sync && npm run test:markdown-constructs",
@@ -120,7 +132,11 @@
120
132
  "test:markdown-constructs": "node scripts/test-markdown-constructs.mjs",
121
133
  "test:theme-presets": "node scripts/test-theme-presets.mjs",
122
134
  "test:presentation-contract": "node scripts/test-presentation-contract.mjs",
135
+ "test:presentation-review": "node scripts/test-presentation-review-fixture.mjs",
123
136
  "test:presentation:browser": "node scripts/test-navigation.mjs --site-dir fixtures/preset-baseline/site tests/presentation-contract.spec.ts",
137
+ "test:table-layout:top": "node scripts/test-navigation.mjs --site-dir fixtures/top-navigation/site tests/table-width-top.spec.ts",
138
+ "test:table-sorting": "node scripts/test-navigation.mjs --site-dir fixtures/table-sorting/site tests/table-sorting.spec.ts",
139
+ "test:table-context:browser": "node scripts/test-navigation.mjs --site-dir fixtures/presentation-review/site tests/table-responsive-context.spec.ts",
124
140
  "test:navigation-surfaces:browser": "npm run test:navigation-surfaces:top && npm run test:navigation-surfaces:tree",
125
141
  "test:navigation-surfaces:top": "node scripts/test-navigation.mjs --site-dir fixtures/content-model-v2/site tests/navigation-surfaces-top.spec.ts",
126
142
  "test:navigation-surfaces:tree": "node scripts/test-navigation.mjs --site-dir fixtures/preset-baseline/site tests/presentation-contract.spec.ts",
@@ -134,6 +150,8 @@
134
150
  "test:site-public": "node scripts/test-site-public.mjs",
135
151
  "test:cli-discovery": "node scripts/test-cli-discovery.mjs",
136
152
  "test:dev-local": "node scripts/test-dev-local.mjs",
153
+ "test:review-environments": "node scripts/test-review-environments.mjs",
154
+ "test:review-environments:browser": "node scripts/test-review-environments-browser.mjs",
137
155
  "test:engine-commands": "node scripts/test-engine-commands.mjs",
138
156
  "test:editor-language": "node scripts/test-editor-language-service.mjs && npm --prefix editors/vscode run check",
139
157
  "test:editor-integration": "npm --prefix editors/vscode run test:integration",
@@ -149,6 +167,7 @@
149
167
  "test:navigation:stress": "node scripts/test-navigation.mjs tests/navigation-stress.spec.ts",
150
168
  "test:navigation:preview": "node scripts/test-navigation-preview.mjs",
151
169
  "package:check": "node scripts/test-package-check.mjs",
170
+ "test:migration-check": "node scripts/test-migration-check.mjs",
152
171
  "release:publish": "npm publish --access public --registry=https://registry.npmjs.org/ --cache /private/tmp/norna-npm-cache",
153
172
  "release:patch": "node scripts/release.mjs patch",
154
173
  "release:minor": "node scripts/release.mjs minor",
@@ -163,7 +182,9 @@
163
182
  "embla-carousel": "^8.6.0",
164
183
  "js-yaml": "^4.3.1",
165
184
  "pagefind": "1.5.2",
166
- "satteri": "^0.9.1"
185
+ "parse5": "7.3.0",
186
+ "satteri": "^0.9.1",
187
+ "yaml": "2.9.0"
167
188
  },
168
189
  "devDependencies": {
169
190
  "@playwright/test": "^1.61.1",
@@ -0,0 +1,121 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "description": "Show related choices as cards with optional images and links. Set link to make the whole card clickable.",
4
+ "type": "object",
5
+ "additionalProperties": false,
6
+ "required": [
7
+ "items"
8
+ ],
9
+ "properties": {
10
+ "layout": {
11
+ "type": "string",
12
+ "description": "Place each card image above, left, or right of its text. Defaults to image-top.",
13
+ "default": "image-top",
14
+ "enum": [
15
+ "image-top",
16
+ "image-left",
17
+ "image-right"
18
+ ],
19
+ "minLength": 1,
20
+ "pattern": "^(?=.*\\S)[^\\x00-\\x1F\\x7F-\\x9F\\u2028\\u2029]+$(?![\\s\\S])"
21
+ },
22
+ "flow": {
23
+ "type": "string",
24
+ "description": "Arrange cards as a responsive grid or a vertical stack. Defaults to grid.",
25
+ "default": "grid",
26
+ "enum": [
27
+ "grid",
28
+ "stack"
29
+ ],
30
+ "minLength": 1,
31
+ "pattern": "^(?=.*\\S)[^\\x00-\\x1F\\x7F-\\x9F\\u2028\\u2029]+$(?![\\s\\S])"
32
+ },
33
+ "size": {
34
+ "type": "string",
35
+ "description": "Set the coordinated card and image size. Defaults to m.",
36
+ "default": "m",
37
+ "enum": [
38
+ "s",
39
+ "m",
40
+ "l",
41
+ "xl"
42
+ ],
43
+ "minLength": 1,
44
+ "pattern": "^(?=.*\\S)[^\\x00-\\x1F\\x7F-\\x9F\\u2028\\u2029]+$(?![\\s\\S])"
45
+ },
46
+ "width": {
47
+ "type": "string",
48
+ "description": "Override the root theme's maximum width for this card list.",
49
+ "enum": [
50
+ "text",
51
+ "narrow",
52
+ "normal",
53
+ "wide"
54
+ ],
55
+ "minLength": 1,
56
+ "pattern": "^(?=.*\\S)[^\\x00-\\x1F\\x7F-\\x9F\\u2028\\u2029]+$(?![\\s\\S])"
57
+ },
58
+ "items": {
59
+ "type": "array",
60
+ "minItems": 1,
61
+ "items": {
62
+ "type": "object",
63
+ "additionalProperties": false,
64
+ "required": [
65
+ "title"
66
+ ],
67
+ "properties": {
68
+ "title": {
69
+ "type": "string",
70
+ "description": "Start another card. Every card requires a title.",
71
+ "minLength": 1,
72
+ "pattern": "^(?=.*\\S)[^\\x00-\\x1F\\x7F-\\x9F\\u2028\\u2029]+$(?![\\s\\S])"
73
+ },
74
+ "text": {
75
+ "type": "string",
76
+ "description": "Optional card text.",
77
+ "minLength": 1,
78
+ "pattern": "^(?=[\\s\\S]*\\S)[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x9F]*$(?![\\s\\S])"
79
+ },
80
+ "image": {
81
+ "type": "string",
82
+ "description": "Optional managed image filename.",
83
+ "minLength": 1,
84
+ "pattern": "^[a-zA-Z0-9][a-zA-Z0-9.-]*\\.(?:[jJ][pP][eE]?[gG]|[pP][nN][gG]|[sS][vV][gG])$(?![\\s\\S])"
85
+ },
86
+ "link": {
87
+ "type": "string",
88
+ "description": "Optional URL opened when the card is activated.",
89
+ "minLength": 1,
90
+ "pattern": "^(?=.*\\S)[^\\x00-\\x1F\\x7F-\\x9F\\u2028\\u2029]+$(?![\\s\\S])"
91
+ },
92
+ "badge-text": {
93
+ "type": "string",
94
+ "description": "Optional short badge displayed on the card.",
95
+ "minLength": 1,
96
+ "pattern": "^(?=.*\\S)[^\\x00-\\x1F\\x7F-\\x9F\\u2028\\u2029]+$(?![\\s\\S])"
97
+ }
98
+ },
99
+ "anyOf": [
100
+ {
101
+ "required": [
102
+ "text"
103
+ ]
104
+ },
105
+ {
106
+ "required": [
107
+ "image"
108
+ ]
109
+ },
110
+ {
111
+ "required": [
112
+ "link"
113
+ ]
114
+ }
115
+ ]
116
+ }
117
+ }
118
+ },
119
+ "$id": "https://janga.github.io/norna/schemas/card-list.schema.json",
120
+ "title": "Norna card-list"
121
+ }
@@ -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.24/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.26/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.24/docs/pages.md#navigation-categories)"
19
+ "markdownDescription": "```yaml\nlabel: Guides\n```\n\n`category.yaml` groups child pages without editorial content. Its URL opens the first listed direct page, or a generated child list when the first child is a category.\n\n[Navigation category reference](https://github.com/janga/norna/blob/v0.7.26/docs/pages.md#navigation-categories)"
20
20
  }