@janga/norna 0.7.23 → 0.7.25

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 (82) hide show
  1. package/README.md +14 -18
  2. package/astro.config.mjs +14 -0
  3. package/bin/norna-cli.mjs +6 -0
  4. package/package.json +25 -2
  5. package/schemas/category.schema.json +2 -2
  6. package/schemas/config.schema.json +80 -15
  7. package/schemas/content-frontmatter.schema.json +7 -7
  8. package/schemas/page-theme.schema.json +26 -26
  9. package/schemas/sitewide-content.schema.json +18 -18
  10. package/schemas/theme.schema.json +246 -246
  11. package/scripts/build-site.mjs +1 -0
  12. package/scripts/check-config.mjs +16 -1
  13. package/scripts/dev-local.mjs +106 -11
  14. package/scripts/generate-search-index.mjs +57 -0
  15. package/scripts/init-site.mjs +3 -0
  16. package/scripts/lib/code-fence-metadata.mjs +228 -0
  17. package/scripts/lib/edit-source-link.mjs +102 -0
  18. package/scripts/lib/editor-language-service.mjs +32 -12
  19. package/scripts/lib/image-presentation.mjs +4 -0
  20. package/scripts/lib/navigation-model.mjs +34 -13
  21. package/scripts/lib/navigation-review.mjs +396 -0
  22. package/scripts/lib/norna-markdown-blocks.mjs +164 -26
  23. package/scripts/lib/norna-markdown-render-plugin.mjs +64 -1
  24. package/scripts/lib/page-aliases.mjs +21 -1
  25. package/scripts/lib/page-markdown.mjs +32 -1
  26. package/scripts/lib/page-move-plan.mjs +659 -0
  27. package/scripts/lib/presentation-palette-metadata.mjs +1 -1
  28. package/scripts/lib/presentation.mjs +1 -10
  29. package/scripts/lib/project-config.mjs +141 -5
  30. package/scripts/lib/public-asset-conventions.mjs +36 -2
  31. package/scripts/lib/schema-definitions.mjs +30 -5
  32. package/scripts/lib/schema-editor-metadata.mjs +36 -4
  33. package/scripts/lib/schema-value-definitions.mjs +4 -1
  34. package/scripts/lib/semantic-callouts.mjs +128 -0
  35. package/scripts/lib/site-content.mjs +2 -1
  36. package/scripts/lib/site-link-graph.mjs +33 -2
  37. package/scripts/lib/site-navigation-tree.mjs +85 -0
  38. package/scripts/lib/site-paths.mjs +14 -2
  39. package/scripts/lib/social-image-assets.mjs +30 -0
  40. package/scripts/lib/table-render-plugin.mjs +33 -0
  41. package/scripts/lib/theme-presets.mjs +2 -2
  42. package/scripts/lib/theme-profiles.mjs +0 -4
  43. package/scripts/move-site-page.mjs +256 -0
  44. package/scripts/review-navigation.mjs +32 -0
  45. package/scripts/sync-content-sections.mjs +67 -4
  46. package/scripts/sync-site-public.mjs +24 -5
  47. package/src/components/CardList.astro +1 -0
  48. package/src/components/CodeBlockCopyScript.astro +11 -5
  49. package/src/components/EditSourceLink.astro +17 -0
  50. package/src/components/ImageCarousel.astro +9 -7
  51. package/src/components/ImageStack.astro +34 -9
  52. package/src/components/ImageStackEnhancement.astro +331 -0
  53. package/src/components/NavigationPageTree.astro +66 -55
  54. package/src/components/NavigationTreeControls.astro +77 -0
  55. package/src/components/PageAliasRedirect.astro +1 -1
  56. package/src/components/PageContentsNavigation.astro +2 -3
  57. package/src/components/PageList.astro +33 -0
  58. package/src/components/PageSequenceNavigation.astro +37 -0
  59. package/src/components/SearchPage.astro +151 -0
  60. package/src/components/SectionNavigationScript.astro +45 -7
  61. package/src/components/SiteNavigation.astro +102 -51
  62. package/src/components/SitePage.astro +107 -39
  63. package/src/components/SiteSection.astro +11 -3
  64. package/src/components/SiteTreeNavigation.astro +11 -1
  65. package/src/components/TableOverflowScript.astro +251 -0
  66. package/src/components/TreeNavigationScript.astro +271 -34
  67. package/src/layouts/BaseLayout.astro +83 -2
  68. package/src/lib/generatedImages.ts +18 -0
  69. package/src/lib/sectionContent.ts +36 -30
  70. package/src/lib/siteNavigation.ts +31 -52
  71. package/src/lib/sitePages.ts +6 -3
  72. package/src/lib/sitePublicAssets.ts +1 -0
  73. package/src/pages/404.astro +110 -0
  74. package/src/pages/[...slug].astro +15 -5
  75. package/src/styles/content.css +538 -39
  76. package/src/styles/media.css +187 -8
  77. package/src/styles/navigation.css +199 -3
  78. package/src/styles/page-layout.css +481 -100
  79. package/src/styles/responsive.css +144 -28
  80. package/starters/basic/README.md +6 -19
  81. package/starters/basic/package.json +1 -0
  82. package/starters/basic/site/pages/000-home/content.md +13 -50
@@ -25,7 +25,7 @@
25
25
  margin-bottom: var(--space-content-block-gap);
26
26
  }
27
27
 
28
- .section-body > :is(.image-stack, .managed-images, .card-list) {
28
+ .content-block-note-lane-boundary {
29
29
  clear: both;
30
30
  }
31
31
 
@@ -215,7 +215,7 @@
215
215
  min-width: 0;
216
216
  }
217
217
 
218
- @media (min-width: 701px) {
218
+ @media (min-width: 961px) {
219
219
  :root[data-image-presentation='prose-aligned'] .site-page-layout-tree .section-body {
220
220
  grid-template-columns: minmax(0, var(--layout-reading-width)) minmax(0, 1fr);
221
221
  }
@@ -227,16 +227,44 @@
227
227
 
228
228
  .managed-image-item {
229
229
  display: grid;
230
- gap: 0.55rem;
230
+ gap: 0;
231
231
  align-content: start;
232
232
  margin: 0;
233
233
  }
234
234
 
235
+ .image-stack {
236
+ --image-caption-inline-gap: 0.75rem;
237
+ }
238
+
235
239
  .image-stack .managed-image-item {
236
240
  width: var(--layout-stack-item-width);
237
241
  margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
238
242
  }
239
243
 
244
+ @media (min-width: 1101px) {
245
+ .image-stack .managed-image-item[data-image-caption-placement='persistent'] {
246
+ position: relative;
247
+ padding-block-end: var(--image-persistent-caption-reserve, 0);
248
+ }
249
+
250
+ .image-stack .managed-image-item[data-image-caption-placement='persistent'] > .image-meta {
251
+ position: absolute;
252
+ inset-block-start: var(--image-persistent-caption-block-start, 0);
253
+ inset-block-end: var(--image-persistent-caption-block-end, 0);
254
+ inset-inline-start: var(--image-persistent-caption-inline-start);
255
+ width: var(--image-persistent-caption-width, var(--section-note-width, 12rem));
256
+ margin: 0;
257
+ text-align: start;
258
+ }
259
+
260
+ .image-stack .managed-image-item[data-image-caption-placement='persistent'] > .image-meta .image-details {
261
+ position: sticky;
262
+ top: calc(var(--site-top-anchor-offset) + 1rem);
263
+ display: block;
264
+ padding: 0;
265
+ }
266
+ }
267
+
240
268
  .managed-image-frame {
241
269
  display: grid;
242
270
  width: var(--layout-media-width);
@@ -246,6 +274,57 @@
246
274
  place-items: center;
247
275
  }
248
276
 
277
+ .managed-image-inspection-link {
278
+ position: relative;
279
+ display: grid;
280
+ width: min(100%, var(--managed-image-intrinsic-width, 100%));
281
+ max-width: 100%;
282
+ place-items: center;
283
+ color: inherit;
284
+ }
285
+
286
+ :root[data-image-presentation='centered-fit'] .managed-image-inspection-link {
287
+ width: min(
288
+ 100%,
289
+ var(--managed-image-intrinsic-width, 100%),
290
+ calc(var(--image-max-height) * var(--managed-image-aspect-ratio, 100))
291
+ );
292
+ }
293
+
294
+ .managed-image-inspection-link:focus-visible {
295
+ outline: var(--focus-indicator-width) solid var(--color-focus-ring);
296
+ outline-offset: 0.35rem;
297
+ box-shadow: 0 0 0 calc(var(--focus-indicator-width) * 2) var(--color-focus-ring-contrast);
298
+ }
299
+
300
+ .managed-image-inspection-link[data-image-inspection-available='true'] {
301
+ cursor: zoom-in;
302
+ }
303
+
304
+ .managed-image-inspection-affordance {
305
+ position: absolute;
306
+ top: 0.65rem;
307
+ right: 0.65rem;
308
+ display: none;
309
+ width: 2.25rem;
310
+ height: 2.25rem;
311
+ place-items: center;
312
+ border-radius: 999px;
313
+ background: var(--color-control-background);
314
+ box-shadow: 0 0.125rem 0.5rem rgb(0 0 0 / 18%);
315
+ color: var(--color-control-text);
316
+ pointer-events: none;
317
+ }
318
+
319
+ .managed-image-inspection-link[data-image-inspection-available='true'] .managed-image-inspection-affordance {
320
+ display: grid;
321
+ }
322
+
323
+ .managed-image-inspection-affordance svg {
324
+ width: 1.125rem;
325
+ height: 1.125rem;
326
+ }
327
+
249
328
  .managed-image {
250
329
  display: block;
251
330
  width: auto;
@@ -257,6 +336,111 @@
257
336
  object-fit: contain;
258
337
  }
259
338
 
339
+ :root[data-image-inspector-open='true'] {
340
+ overflow: hidden;
341
+ }
342
+
343
+ .image-inspector {
344
+ width: min(calc(100% - 2rem), 96rem);
345
+ height: calc(100svh - 2rem);
346
+ max-width: none;
347
+ max-height: none;
348
+ margin: auto;
349
+ border: 1px solid var(--color-border);
350
+ border-radius: var(--corner-radius-large, 8px);
351
+ padding: 0;
352
+ background: var(--color-page);
353
+ color: var(--color-primary-text);
354
+ box-shadow: 0 1rem 3rem rgb(0 0 0 / 28%);
355
+ overflow: hidden;
356
+ }
357
+
358
+ .image-inspector::backdrop {
359
+ background: rgb(0 0 0 / 62%);
360
+ }
361
+
362
+ .image-inspector-layout {
363
+ display: grid;
364
+ grid-template-rows: auto minmax(0, 1fr) auto;
365
+ gap: 0.75rem;
366
+ height: 100%;
367
+ padding: 0.75rem;
368
+ }
369
+
370
+ .image-inspector-controls {
371
+ display: flex;
372
+ justify-content: flex-end;
373
+ gap: 0.5rem;
374
+ }
375
+
376
+ .image-inspector-controls button {
377
+ display: grid;
378
+ width: 2.75rem;
379
+ height: 2.75rem;
380
+ place-items: center;
381
+ border: 1px solid var(--color-border);
382
+ border-radius: var(--corner-radius-small, 2px);
383
+ padding: 0;
384
+ background: var(--color-surface-soft-background);
385
+ color: var(--color-surface-soft-text);
386
+ cursor: pointer;
387
+ }
388
+
389
+ .image-inspector-controls button:hover,
390
+ .image-inspector-controls button:active {
391
+ background: var(--color-surface-emphasis-background);
392
+ color: var(--color-surface-emphasis-text);
393
+ }
394
+
395
+ .image-inspector-controls button:focus-visible {
396
+ outline: var(--focus-indicator-width) solid var(--color-focus-ring);
397
+ outline-offset: 2px;
398
+ box-shadow: 0 0 0 calc(var(--focus-indicator-width) * 2) var(--color-focus-ring-contrast);
399
+ }
400
+
401
+ .image-inspector-controls [hidden] {
402
+ display: none;
403
+ }
404
+
405
+ .image-inspector-media {
406
+ display: grid;
407
+ min-width: 0;
408
+ min-height: 0;
409
+ place-items: center;
410
+ overflow: auto;
411
+ overscroll-behavior: contain;
412
+ }
413
+
414
+ .image-inspector-media img {
415
+ display: block;
416
+ width: auto;
417
+ height: auto;
418
+ margin: auto;
419
+ }
420
+
421
+ .image-inspector-media[data-image-inspector-mode='fit'] img {
422
+ max-width: 100%;
423
+ max-height: 100%;
424
+ }
425
+
426
+ .image-inspector-media[data-image-inspector-mode='actual'] {
427
+ display: block;
428
+ }
429
+
430
+ .image-inspector-media[data-image-inspector-mode='actual'] img {
431
+ max-width: none;
432
+ max-height: none;
433
+ }
434
+
435
+ .image-inspector-caption {
436
+ max-width: 72ch;
437
+ margin: 0 auto;
438
+ color: var(--color-secondary-text);
439
+ font-size: 0.95rem;
440
+ line-height: 1.5;
441
+ text-align: center;
442
+ }
443
+
260
444
  .managed-image.managed-image-landscape {
261
445
  width: 100%;
262
446
  max-height: none;
@@ -291,10 +475,6 @@
291
475
  outline: none;
292
476
  }
293
477
 
294
- :root[data-image-presentation='prose-aligned'] .image-carousel {
295
- --layout-carousel-width: min(100%, var(--layout-media-width));
296
- }
297
-
298
478
  .image-carousel:focus-visible {
299
479
  outline: var(--focus-indicator-width) solid var(--color-focus-ring);
300
480
  outline-offset: 0.5rem;
@@ -317,7 +497,6 @@
317
497
  }
318
498
 
319
499
  :root[data-image-presentation='prose-aligned'] .image-carousel-stage {
320
- max-height: none;
321
500
  margin-inline: 0 auto;
322
501
  }
323
502
 
@@ -35,6 +35,37 @@
35
35
  margin-left: auto;
36
36
  }
37
37
 
38
+ .site-search-link {
39
+ display: grid;
40
+ place-items: center;
41
+ flex: 0 0 auto;
42
+ width: 2.25rem;
43
+ height: 2.25rem;
44
+ border: 1px solid color-mix(in srgb, currentColor 38%, transparent);
45
+ border-radius: 50%;
46
+ color: currentColor;
47
+ text-decoration: none;
48
+ transition: border-color 0.18s ease, background-color 0.18s ease;
49
+ }
50
+
51
+ .site-search-link:hover,
52
+ .site-search-link[aria-current='page'] {
53
+ border-color: currentColor;
54
+ background: color-mix(in srgb, currentColor 9%, transparent);
55
+ }
56
+
57
+ .site-search-link:focus-visible {
58
+ outline: var(--focus-indicator-width) solid var(--color-focus-ring);
59
+ outline-offset: 2px;
60
+ }
61
+
62
+ .site-search-link svg {
63
+ display: block;
64
+ width: 1.05rem;
65
+ height: 1.05rem;
66
+ stroke-width: 2;
67
+ }
68
+
38
69
  .site-nav-leading {
39
70
  display: flex;
40
71
  align-items: center;
@@ -68,7 +99,7 @@
68
99
  transition: border-color 0.18s ease, background-color 0.18s ease;
69
100
  }
70
101
 
71
- :root[data-focus-reading='on'] .display-settings summary {
102
+ :root[data-reader-preferences-ready='true'][data-focus-reading='on'] .display-settings summary {
72
103
  grid-template-columns: auto auto;
73
104
  gap: 0.4rem;
74
105
  width: auto;
@@ -111,7 +142,7 @@
111
142
  white-space: nowrap;
112
143
  }
113
144
 
114
- :root[data-focus-reading='on'] .display-settings-focus-status {
145
+ :root[data-reader-preferences-ready='true'][data-focus-reading='on'] .display-settings-focus-status {
115
146
  display: block;
116
147
  }
117
148
 
@@ -399,6 +430,171 @@
399
430
  display: none;
400
431
  }
401
432
 
433
+ .mobile-nav-trigger-icon {
434
+ display: block;
435
+ width: 1rem;
436
+ height: 1rem;
437
+ stroke-width: 2;
438
+ }
439
+
440
+ .mobile-nav-trigger-close,
441
+ .mobile-nav-menu[open] .mobile-nav-trigger-open {
442
+ display: none;
443
+ }
444
+
445
+ .mobile-nav-menu[open] .mobile-nav-trigger-close {
446
+ display: block;
447
+ }
448
+
449
+ .mobile-nav-panel-actions {
450
+ display: flex;
451
+ justify-content: flex-end;
452
+ width: min(100%, 32rem);
453
+ margin: 0 auto 0.5rem;
454
+ }
455
+
456
+ .mobile-nav-close {
457
+ display: grid;
458
+ width: 2.75rem;
459
+ height: 2.75rem;
460
+ place-items: center;
461
+ border: 1px solid currentColor;
462
+ border-radius: 50%;
463
+ padding: 0;
464
+ background: transparent;
465
+ color: currentColor;
466
+ cursor: pointer;
467
+ }
468
+
469
+ .mobile-nav-close:hover,
470
+ .mobile-nav-close:focus-visible {
471
+ background: color-mix(in srgb, currentColor 9%, transparent);
472
+ }
473
+
474
+ .mobile-nav-close:focus-visible {
475
+ outline: var(--focus-indicator-width) solid var(--color-focus-ring);
476
+ outline-offset: 2px;
477
+ }
478
+
479
+ .mobile-nav-close svg {
480
+ width: 1.1rem;
481
+ height: 1.1rem;
482
+ stroke-width: 2;
483
+ }
484
+
485
+ .mobile-navigation-open {
486
+ overflow: hidden;
487
+ }
488
+
489
+ @media (min-width: 701px) {
490
+ .mobile-nav-menu {
491
+ position: relative;
492
+ flex: 0 0 auto;
493
+ margin-left: auto;
494
+ }
495
+
496
+ :root[data-reader-preferences-ready='true'][data-focus-reading='on'] .mobile-nav-menu {
497
+ display: block;
498
+ }
499
+
500
+ .mobile-nav-menu > summary {
501
+ display: flex;
502
+ align-items: center;
503
+ gap: 0.5rem;
504
+ min-height: 2.75rem;
505
+ border: 1px solid currentColor;
506
+ padding: 0.55rem 0.75rem;
507
+ color: var(--site-top-text-color, var(--color-primary-text));
508
+ font-size: 0.72rem;
509
+ font-weight: 700;
510
+ letter-spacing: 0.1em;
511
+ line-height: 1;
512
+ list-style: none;
513
+ text-transform: uppercase;
514
+ }
515
+
516
+ .mobile-nav-menu > summary::-webkit-details-marker {
517
+ display: none;
518
+ }
519
+
520
+ .mobile-nav-panel {
521
+ position: fixed;
522
+ top: var(--site-top-anchor-offset);
523
+ right: 0;
524
+ bottom: 0;
525
+ left: 0;
526
+ z-index: 20;
527
+ width: 100%;
528
+ max-height: none;
529
+ border-top: 1px solid color-mix(in srgb, currentColor 24%, transparent);
530
+ padding: clamp(1.25rem, 5vw, 2rem) var(--content-gutter) max(1.5rem, env(safe-area-inset-bottom));
531
+ background: var(--site-top-background-color, var(--color-page));
532
+ box-shadow: 0 1.5rem 3.5rem rgb(0 0 0 / 0.32);
533
+ color: var(--site-top-text-color, var(--color-text));
534
+ overflow-y: auto;
535
+ overscroll-behavior: contain;
536
+ }
537
+
538
+ .mobile-site-nav {
539
+ width: min(100%, 32rem);
540
+ margin: 0 auto;
541
+ }
542
+
543
+ .mobile-nav-panel h2 {
544
+ margin: 0 0 1.25rem;
545
+ font-size: 1.4rem;
546
+ font-weight: 650;
547
+ letter-spacing: 0;
548
+ line-height: 1.2;
549
+ text-transform: none;
550
+ }
551
+
552
+ .mobile-nav-panel .navigation-tree-controls {
553
+ position: static;
554
+ margin-bottom: 1rem;
555
+ padding-bottom: 1rem;
556
+ background: var(--site-top-background-color, var(--color-page));
557
+ }
558
+
559
+ .mobile-nav-panel a {
560
+ font-family: inherit;
561
+ font-size: 0.9rem;
562
+ letter-spacing: 0;
563
+ line-height: 1.4;
564
+ text-transform: none;
565
+ }
566
+
567
+ .navigation-page-tree-mobile .navigation-page-link {
568
+ display: block;
569
+ border-radius: var(--corner-radius-small, 2px);
570
+ padding: 0.45rem 0.3rem 0.45rem var(--tree-disclosure-offset);
571
+ color: var(--color-secondary-text);
572
+ text-decoration: none;
573
+ }
574
+
575
+ .navigation-page-tree-mobile .navigation-page-branch-content {
576
+ margin: 0.1rem 0 0.2rem 0.25rem;
577
+ border-left: 1px solid color-mix(in srgb, currentColor 16%, transparent);
578
+ padding-left: 0.75rem;
579
+ }
580
+
581
+ .navigation-page-tree-mobile .navigation-page-tree-mobile {
582
+ margin: 0.15rem 0;
583
+ border-left: 0;
584
+ padding-left: 0;
585
+ }
586
+ }
587
+
588
+ @media (min-width: 701px) and (max-width: 960px) {
589
+ .site-top[data-navigation-mode='tree'] .site-nav {
590
+ display: none;
591
+ }
592
+
593
+ .site-top[data-navigation-mode='tree'] .mobile-nav-menu {
594
+ display: block;
595
+ }
596
+ }
597
+
402
598
  .page-nav {
403
599
  border-top: 1px solid color-mix(in srgb, currentColor 14%, transparent);
404
600
  }
@@ -409,7 +605,7 @@
409
605
 
410
606
  .page-nav-inner {
411
607
  display: flex;
412
- align-items: center;
608
+ align-items: baseline;
413
609
  justify-content: center;
414
610
  gap: clamp(1.1rem, 2.5vw, 2rem);
415
611
  width: min(calc(100% - (var(--content-gutter) * 2)), var(--page-width));