@janga/norna 0.7.27 → 0.7.28

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 (109) hide show
  1. package/README.md +37 -28
  2. package/astro.config.mjs +19 -1
  3. package/bin/norna-cli.mjs +5 -3
  4. package/package.json +9 -5
  5. package/schemas/card-list.schema.json +1 -1
  6. package/schemas/config.schema.json +66 -66
  7. package/schemas/content-frontmatter.schema.json +16 -7
  8. package/schemas/manifest.json +49 -3
  9. package/schemas/page-theme.schema.json +1585 -41
  10. package/schemas/root-theme.schema.json +1767 -0
  11. package/schemas/sitewide-content.schema.json +18 -18
  12. package/schemas/theme.schema.json +243 -243
  13. package/scripts/add-site-node.mjs +13 -161
  14. package/scripts/build-site.mjs +11 -6
  15. package/scripts/check-config.mjs +7 -23
  16. package/scripts/dev-local.mjs +17 -10
  17. package/scripts/export-theme-preset.mjs +2 -2
  18. package/scripts/generate-images.mjs +7 -6
  19. package/scripts/generate-schemas.mjs +9 -6
  20. package/scripts/lib/category-destinations.mjs +13 -12
  21. package/scripts/lib/documentation-links.mjs +1 -1
  22. package/scripts/lib/documentation-routes.json +67 -60
  23. package/scripts/lib/docusaurus-migration-audit.mjs +9 -6
  24. package/scripts/lib/editor-file-policy.mjs +18 -0
  25. package/scripts/lib/editor-language-service.mjs +53 -55
  26. package/scripts/lib/editor-page-addresses.mjs +55 -0
  27. package/scripts/lib/editor-page-placement.mjs +172 -0
  28. package/scripts/lib/editor-site-editing-tree.mjs +146 -0
  29. package/scripts/lib/editor-site-files.mjs +153 -0
  30. package/scripts/lib/editor-site-links.mjs +79 -0
  31. package/scripts/lib/editor-site-tree.mjs +151 -0
  32. package/scripts/lib/editor-source-files.mjs +87 -0
  33. package/scripts/lib/editor-theme-help.mjs +43 -0
  34. package/scripts/lib/locale-registry.mjs +1 -1
  35. package/scripts/lib/locales/en.mjs +1 -1
  36. package/scripts/lib/navigation-model.mjs +2 -44
  37. package/scripts/lib/navigation-review.mjs +14 -50
  38. package/scripts/lib/norna-markdown-blocks.mjs +1 -1
  39. package/scripts/lib/page-aliases.mjs +3 -1
  40. package/scripts/lib/page-model.mjs +17 -20
  41. package/scripts/lib/page-move-apply.mjs +117 -0
  42. package/scripts/lib/page-move-plan.mjs +27 -59
  43. package/scripts/lib/presentation.mjs +3 -3
  44. package/scripts/lib/project-config.mjs +7 -8
  45. package/scripts/lib/schema-definitions.mjs +11 -38
  46. package/scripts/lib/schema-editor-metadata.mjs +12 -59
  47. package/scripts/lib/schema-value-definitions.mjs +1 -1
  48. package/scripts/lib/site-content.mjs +7 -24
  49. package/scripts/lib/site-conventions.mjs +19 -1
  50. package/scripts/lib/site-navigation-tree.mjs +2 -7
  51. package/scripts/lib/site-node-create.mjs +169 -0
  52. package/scripts/lib/site-paths.mjs +22 -10
  53. package/scripts/lib/site-structure.mjs +72 -82
  54. package/scripts/lib/site-upgrade.mjs +30 -0
  55. package/scripts/lib/source-files.mjs +34 -0
  56. package/scripts/lib/theme-config.mjs +26 -68
  57. package/scripts/lib/theme-packages.mjs +47 -0
  58. package/scripts/lib/theme-presets.mjs +20 -53
  59. package/scripts/lib/typography.mjs +2 -2
  60. package/scripts/lib/yaml-config.mjs +1 -1
  61. package/scripts/lib/yaml-source-edit.mjs +94 -0
  62. package/scripts/move-site-page.mjs +3 -124
  63. package/scripts/show-typography.mjs +32 -17
  64. package/scripts/sync-content-sections.mjs +9 -7
  65. package/scripts/sync-site-public.mjs +1 -1
  66. package/scripts/upgrade-site.mjs +17 -0
  67. package/src/components/AreaNavigationMenu.astro +24 -0
  68. package/src/components/AreaNavigationPanel.astro +55 -0
  69. package/src/components/AreaNavigationSwitcher.astro +30 -0
  70. package/src/components/ImageStackEnhancement.astro +0 -7
  71. package/src/components/NavigationContinuity.astro +26 -0
  72. package/src/components/NavigationPageTree.astro +13 -4
  73. package/src/components/NavigationState.astro +11 -0
  74. package/src/components/NavigationTreeControls.astro +3 -2
  75. package/src/components/SearchPage.astro +9 -1
  76. package/src/components/SectionNavigationScript.astro +106 -26
  77. package/src/components/SiteNavigation.astro +45 -20
  78. package/src/components/SitePage.astro +37 -61
  79. package/src/components/SiteTreeNavigation.astro +38 -18
  80. package/src/components/TopPageMenu.astro +4 -3
  81. package/src/components/TreeNavigationScript.astro +50 -57
  82. package/src/content.config.ts +10 -8
  83. package/src/layouts/BaseLayout.astro +15 -39
  84. package/src/lib/areaNavigation.ts +42 -0
  85. package/src/lib/navigationContinuity.ts +212 -0
  86. package/src/lib/navigationFollowing.ts +28 -18
  87. package/src/lib/navigationState.mjs +88 -0
  88. package/src/lib/navigationStateScript.mjs +76 -0
  89. package/src/lib/navigationVisibility.ts +9 -0
  90. package/src/lib/pageThemes.ts +5 -42
  91. package/src/lib/sectionContent.ts +3 -2
  92. package/src/lib/siteNavigation.ts +6 -0
  93. package/src/lib/sitePages.ts +9 -6
  94. package/src/pages/404.astro +1 -1
  95. package/src/pages/[...slug].astro +5 -15
  96. package/src/pages/index.astro +1 -3
  97. package/src/styles/area-navigation.css +399 -0
  98. package/src/styles/content.css +2 -29
  99. package/src/styles/navigation-continuity.css +163 -0
  100. package/src/styles/page-layout.css +57 -68
  101. package/src/styles/responsive.css +0 -4
  102. package/starters/basic/README.md +9 -8
  103. package/starters/basic/site/{pages/000-home → root}/content.md +2 -2
  104. package/schemas/category.schema.json +0 -20
  105. package/src/components/PageContentsNavigation.astro +0 -20
  106. /package/starters/basic/site/{pages/000-home → root}/images/.gitkeep +0 -0
  107. /package/starters/basic/site/{theme.yaml → root/tree-theme.yaml} +0 -0
  108. /package/starters/basic/site/{config.yaml → site-config/settings.yaml} +0 -0
  109. /package/starters/basic/site/{sitewide-content.yaml → site-config/shared-content.yaml} +0 -0
@@ -19,11 +19,10 @@
19
19
  .site-page-layout-tree {
20
20
  --tree-layout-width: max(var(--page-width), 86rem);
21
21
  --tree-layout-outer-margin: max(var(--content-gutter), calc((100vw - var(--tree-layout-width)) / 2));
22
- --tree-navigation-width: 14rem;
23
- --contents-navigation-width: 11rem;
22
+ --tree-navigation-width: 16rem;
24
23
  --tree-layout-gap: var(--local-navigation-gap, clamp(1.5rem, 3vw, 3rem));
25
24
  display: grid;
26
- grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr) var(--contents-navigation-width);
25
+ grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr);
27
26
  align-items: start;
28
27
  gap: var(--tree-layout-gap);
29
28
  min-height: calc(100svh - var(--site-top-anchor-offset));
@@ -48,7 +47,7 @@
48
47
  }
49
48
  }
50
49
 
51
- :is(.tree-local-navigation, .mobile-site-nav, .page-contents-navigation) {
50
+ :is(.tree-local-navigation, .mobile-site-nav) {
52
51
  --tree-disclosure-icon-width: 0.9rem;
53
52
  --tree-disclosure-gap: 0.6rem;
54
53
  --tree-disclosure-offset: calc(var(--tree-disclosure-icon-width) + var(--tree-disclosure-gap));
@@ -181,7 +180,7 @@
181
180
  }
182
181
 
183
182
  :root[data-appearance='dark']
184
- :is(.tree-local-navigation, .mobile-site-nav, .page-contents-navigation) {
183
+ :is(.tree-local-navigation, .mobile-site-nav) {
185
184
  --tree-current-item-background: color-mix(
186
185
  in srgb,
187
186
  var(--color-surface-emphasis-background) 64%,
@@ -191,7 +190,7 @@
191
190
 
192
191
  @media (prefers-color-scheme: dark) {
193
192
  :root[data-appearance='system']
194
- :is(.tree-local-navigation, .mobile-site-nav, .page-contents-navigation) {
193
+ :is(.tree-local-navigation, .mobile-site-nav) {
195
194
  --tree-current-item-background: color-mix(
196
195
  in srgb,
197
196
  var(--color-surface-emphasis-background) 64%,
@@ -200,50 +199,11 @@
200
199
  }
201
200
  }
202
201
 
203
- .page-contents-navigation {
204
- color: var(--color-secondary-text);
205
- }
206
-
207
- .page-contents-navigation-rail {
208
- position: sticky;
209
- top: calc(var(--site-top-anchor-offset) + 1.25rem);
210
- z-index: 3;
211
- min-height: 0;
212
- max-height: calc(100svh - var(--site-top-anchor-offset) - 2.5rem);
213
- border-inline-start: 1px solid var(--color-nav-separator);
214
- padding: 1.5rem 0 1.5rem 1rem;
215
- background: var(--color-page);
216
- overflow-y: auto;
217
- overscroll-behavior: contain;
218
- }
219
-
220
- .page-contents-navigation-label {
221
- margin: 0 0 0.65rem;
222
- color: var(--color-primary-text);
223
- font-size: 0.7rem;
224
- font-weight: 700;
225
- letter-spacing: 0;
226
- line-height: 1.3;
227
- }
228
-
229
202
  @media (min-width: 961px) and (max-width: 1280px) {
230
203
  .site-page-layout-tree {
231
204
  --tree-layout-width: max(var(--page-width), 76rem);
232
205
  grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr);
233
206
  }
234
-
235
- .page-contents-navigation-rail {
236
- display: none;
237
- }
238
- }
239
-
240
- @media (min-width: 1281px) {
241
- .site-page-layout-tree[data-page-contents-placement='contents-rail']
242
- .tree-local-navigation .navigation-page-sections,
243
- .site-page-layout-tree[data-page-contents-placement='contents-rail']
244
- .tree-local-navigation .navigation-page-sections-disclosure {
245
- display: none;
246
- }
247
207
  }
248
208
 
249
209
  @media (max-width: 960px) {
@@ -256,8 +216,7 @@
256
216
  width: min(calc(100% - (var(--content-gutter) * 2)), var(--page-width));
257
217
  }
258
218
 
259
- .tree-local-navigation,
260
- .page-contents-navigation {
219
+ .tree-local-navigation {
261
220
  display: none;
262
221
  }
263
222
  }
@@ -268,9 +227,15 @@
268
227
  padding: 0.15rem 0 0.2rem 0.75rem;
269
228
  }
270
229
 
230
+ .navigation-page-tree-sidebar .navigation-page-sections {
231
+ margin-inline-start: 0;
232
+ border-left: 0;
233
+ padding-inline-start: 1rem;
234
+ }
235
+
271
236
  .navigation-page-tree-sidebar
272
- .navigation-page-sections-disclosure > .navigation-page-sections {
273
- margin-inline-start: var(--tree-disclosure-offset);
237
+ .navigation-page-node-page-disclosure > .navigation-page-branch-content > .navigation-page-sections {
238
+ padding-inline-start: 0;
274
239
  }
275
240
 
276
241
  .navigation-page-sections-disclosure > summary {
@@ -292,6 +257,11 @@
292
257
  display: none;
293
258
  }
294
259
 
260
+ .navigation-page-tree-sidebar .navigation-page-sections-disclosure > summary {
261
+ right: 0;
262
+ left: auto;
263
+ }
264
+
295
265
  .navigation-page-sections-disclosure > summary:hover,
296
266
  .navigation-page-sections-disclosure > summary:focus-visible {
297
267
  background: color-mix(in srgb, currentColor 8%, transparent);
@@ -320,8 +290,9 @@
320
290
 
321
291
  .navigation-page-tree-sidebar .navigation-page-link {
322
292
  display: block;
293
+ width: calc(100% - var(--tree-disclosure-offset));
323
294
  border-radius: var(--corner-radius-small, 2px);
324
- padding: 0.375rem 0.3rem 0.375rem var(--tree-disclosure-offset);
295
+ padding: 0.375rem 0.3rem 0.375rem 0;
325
296
  color: var(--color-secondary-text);
326
297
  font-size: 0.84rem;
327
298
  font-weight: 400;
@@ -358,9 +329,8 @@
358
329
  }
359
330
 
360
331
  .navigation-page-tree-sidebar .navigation-page-tree-sidebar {
361
- margin: 0.15rem 0 0.2rem 0.25rem;
362
- border-left: 1px solid color-mix(in srgb, currentColor 16%, transparent);
363
- padding-left: 0.75rem;
332
+ margin: 0.15rem 0 0.2rem;
333
+ padding-left: 1rem;
364
334
  }
365
335
 
366
336
  .navigation-page-disclosure > .navigation-page-summary {
@@ -397,25 +367,27 @@
397
367
  .navigation-page-disclosure-sidebar.navigation-category-disclosure
398
368
  > .navigation-page-summary {
399
369
  display: grid;
400
- grid-template-columns: var(--tree-disclosure-icon-width) minmax(0, 1fr);
401
- column-gap: var(--tree-disclosure-gap);
370
+ grid-template-columns: minmax(0, 1fr) var(--tree-disclosure-offset);
371
+ align-items: start;
402
372
  justify-content: normal;
373
+ padding-inline-end: 0;
403
374
  }
404
375
 
405
376
  .navigation-page-disclosure-sidebar.navigation-category-disclosure
406
377
  > .navigation-page-summary > .navigation-page-summary-title {
407
- grid-column: 2;
378
+ grid-column: 1;
408
379
  width: auto;
380
+ padding-inline-end: 0.3rem;
409
381
  }
410
382
 
411
383
  .navigation-page-disclosure-sidebar.navigation-category-disclosure
412
384
  > .navigation-page-summary > .navigation-page-chevron {
413
- grid-column: 1;
385
+ grid-column: 2;
414
386
  grid-row: 1;
415
387
  display: grid;
416
388
  place-items: center;
417
- width: var(--tree-disclosure-icon-width);
418
- height: 1.35em;
389
+ width: var(--tree-disclosure-offset);
390
+ height: 1.4em;
419
391
  }
420
392
 
421
393
  .navigation-page-node-page-disclosure {
@@ -445,6 +417,26 @@
445
417
  grid-row: 1;
446
418
  }
447
419
 
420
+ /* Labels keep their depth; disclosures share the tree's right edge. */
421
+ .navigation-page-tree-sidebar .navigation-page-node-page-disclosure {
422
+ grid-template-columns: minmax(0, 1fr) var(--tree-disclosure-offset);
423
+ }
424
+
425
+ .navigation-page-tree-sidebar
426
+ .navigation-page-node-page-disclosure > .navigation-page-disclosure {
427
+ grid-column: 2;
428
+ }
429
+
430
+ .navigation-page-tree-sidebar
431
+ .navigation-page-node-page-disclosure > .navigation-page-disclosure > .navigation-page-summary {
432
+ justify-content: normal;
433
+ }
434
+
435
+ .navigation-page-tree-sidebar
436
+ .navigation-page-node-page-disclosure > .navigation-page-open-link {
437
+ grid-column: 1;
438
+ }
439
+
448
440
  .navigation-page-node-page-disclosure > .navigation-page-branch-content {
449
441
  grid-column: 1 / -1;
450
442
  grid-row: 2;
@@ -586,9 +578,8 @@
586
578
 
587
579
  .navigation-page-tree-sidebar .navigation-page-disclosure > .navigation-page-branch-content,
588
580
  .navigation-page-tree-sidebar .navigation-page-node-page-disclosure > .navigation-page-branch-content {
589
- margin: 0.1rem 0 0.2rem 0.25rem;
590
- border-left: 1px solid color-mix(in srgb, currentColor 16%, transparent);
591
- padding-left: 0.75rem;
581
+ margin: 0.1rem 0 0.2rem;
582
+ padding-left: 1rem;
592
583
  }
593
584
 
594
585
  .navigation-page-tree-sidebar .navigation-page-disclosure .navigation-page-tree-sidebar,
@@ -609,6 +600,10 @@
609
600
  list-style: none;
610
601
  }
611
602
 
603
+ .navigation-page-tree-sidebar .page-contents-links ol {
604
+ border-left: 0;
605
+ }
606
+
612
607
  .page-contents-links a {
613
608
  position: relative;
614
609
  display: block;
@@ -626,12 +621,6 @@
626
621
  text-underline-offset: 0.25em;
627
622
  }
628
623
 
629
- .page-contents-navigation-rail .page-contents-links a[aria-current='location'] {
630
- border-radius: var(--corner-radius-small, 2px);
631
- background: var(--tree-current-item-background);
632
- box-shadow: 0 0 0 0.2rem var(--tree-current-item-background);
633
- }
634
-
635
624
  .page-contents-links a[aria-current='location']::before {
636
625
  position: absolute;
637
626
  top: 0.15em;
@@ -385,10 +385,6 @@
385
385
  display: none;
386
386
  }
387
387
 
388
- .page-contents-navigation {
389
- display: none;
390
- }
391
-
392
388
  .page-sequence-navigation {
393
389
  grid-template-columns: 1fr;
394
390
  }
@@ -13,11 +13,11 @@ Open the address printed by the development server. Stop it later with
13
13
  `npm run norna:dev:stop`.
14
14
 
15
15
  Edit shared logo settings, banners, and footer in
16
- `site/sitewide-content.yaml`,
17
- site-wide visual defaults in `site/theme.yaml`, homepage content and section
18
- metadata in `site/pages/000-home/content.md`, and technical settings such as URL
19
- and locale in `site/config.yaml`. Keep managed homepage source images under
20
- `site/pages/000-home/images/` and static public files under `site/public/`.
16
+ `site/site-config/shared-content.yaml`,
17
+ site-wide visual defaults in `site/root/tree-theme.yaml`, homepage content and section
18
+ metadata in `site/root/content.md`, and technical settings such as URL
19
+ and locale in `site/site-config/settings.yaml`. Keep managed homepage source images under
20
+ `site/root/images/` and static public files under `site/public/`.
21
21
 
22
22
  For a GitHub Pages project site without a custom domain, include the repository
23
23
  path in the public URL:
@@ -32,9 +32,10 @@ Norna derives `/repository-name/` as the base path. Use a root URL such as
32
32
  In GitHub repository settings, configure Pages to build from GitHub Actions.
33
33
 
34
34
  Page width, side gutters, content spacing, image sizing, palette, corners, and
35
- site-wide typography are configured in `site/theme.yaml`. A page may use a
36
- limited `theme.yaml` for local text width, content spacing, managed-image
37
- sizing, and section background pattern.
35
+ typography are configured in the required `site/root/tree-theme.yaml`, including
36
+ a `preset`. A descendant `tree-theme.yaml` modifies inherited settings for its
37
+ branch; `page-theme.yaml` affects only its own page. Both accept all visual
38
+ settings. Adding `preset` starts a new base instead of inheriting ancestor values.
38
39
 
39
40
  Commit `package-lock.json` after the first install so GitHub Actions can use
40
41
  `npm ci`.
@@ -10,11 +10,11 @@ of what visitors can find here.
10
10
 
11
11
  ## Welcome
12
12
 
13
- Edit this page in `site/pages/000-home/content.md`. Every H2 starts a section
13
+ Edit this page in `site/root/content.md`. Every H2 starts a section
14
14
  and becomes a destination in this one-page site's navigation.
15
15
 
16
16
  ## Next steps
17
17
 
18
- Add your own text, then choose a preset in `site/theme.yaml`. Put local images
18
+ Add your own text, then choose a preset in `site/root/tree-theme.yaml`. Put local images
19
19
  in this page's `images/` directory and reference them through a Norna image
20
20
  block when the site needs them.
@@ -1,20 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "type": "object",
4
- "properties": {
5
- "label": {
6
- "type": "string",
7
- "minLength": 1,
8
- "description": "Navigation label for a group of child pages without an authored page body.",
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 (current)](https://janga.github.io/norna/reference/site/pages/#page-or-category)\n\n[Norna 0.7.27 source reference](https://github.com/janga/norna/blob/v0.7.27/site/pages/032-reference/pages/010-site/pages/020-pages/content.md#page-or-category)"
10
- }
11
- },
12
- "required": [
13
- "label"
14
- ],
15
- "additionalProperties": false,
16
- "description": "A navigation group without an authored page body. Opening its URL redirects when its first listed direct child is a page; otherwise it shows a generated child list.",
17
- "$id": "https://janga.github.io/norna/schemas/category.schema.json",
18
- "title": "Norna page category",
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 (current)](https://janga.github.io/norna/reference/site/pages/#page-or-category)\n\n[Norna 0.7.27 source reference](https://github.com/janga/norna/blob/v0.7.27/site/pages/032-reference/pages/010-site/pages/020-pages/content.md#page-or-category)"
20
- }
@@ -1,20 +0,0 @@
1
- ---
2
- import projectConfig from '../../scripts/lib/project-config.mjs';
3
- import type { HeadingNavigation } from '../lib/sectionContent';
4
- import PageContentsLinks from './PageContentsLinks.astro';
5
-
6
- interface Props {
7
- headings: HeadingNavigation[];
8
- pageTitle: string;
9
- }
10
-
11
- const { headings, pageTitle } = Astro.props;
12
- const label = `${projectConfig.locale.labels.pageNavigation}: ${pageTitle}`;
13
- ---
14
-
15
- <aside class="page-contents-navigation page-contents-navigation-rail">
16
- <nav aria-label={label}>
17
- <p class="page-contents-navigation-label">{projectConfig.locale.labels.pageNavigation}</p>
18
- <PageContentsLinks headings={headings} variant="desktop" />
19
- </nav>
20
- </aside>