@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
@@ -0,0 +1,523 @@
1
+ /* Cards, managed images, captions, and carousels. */
2
+
3
+ .card-list {
4
+ display: grid;
5
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
6
+ gap: var(--card-list-gap, clamp(0.9rem, 2vw, 1.25rem));
7
+ width: var(--layout-card-list-width);
8
+ margin-block: 0;
9
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
10
+ text-align: left;
11
+ --card-list-width: min(56rem, var(--page-width));
12
+ --layout-card-list-width: min(100%, var(--card-list-width));
13
+ --card-list-gap: clamp(0.9rem, 2vw, 1.25rem);
14
+ --card-list-item-gap: 0.85rem;
15
+ --card-list-padding: clamp(0.9rem, 2vw, 1.15rem);
16
+ --card-list-media-width: 32%;
17
+ --card-list-media-min-width: 7rem;
18
+ --card-list-top-media-width: 20rem;
19
+ --card-list-title-scale: 1;
20
+ --card-list-text-scale: 1;
21
+ }
22
+
23
+ .section-body > .section-markdown:not(:last-child),
24
+ .section-body > :is(.image-stack, .managed-images):not(:last-child) {
25
+ margin-bottom: var(--space-content-block-gap);
26
+ }
27
+
28
+ .section-body > :is(.image-stack, .managed-images, .card-list) {
29
+ clear: both;
30
+ }
31
+
32
+ .section-body > .card-list:not(:last-child) {
33
+ margin-bottom: calc(var(--space-content-block-gap) + var(--space-card-list-after));
34
+ }
35
+
36
+ .section-body > .card-list:last-child {
37
+ margin-bottom: var(--space-card-list-after);
38
+ }
39
+
40
+ .card-list-width-text {
41
+ --card-list-width: var(--reader-text-width, var(--text-width));
42
+ }
43
+
44
+ .card-list-width-narrow {
45
+ --card-list-width: min(48rem, var(--page-width));
46
+ }
47
+
48
+ .card-list-width-wide {
49
+ --card-list-width: var(--page-width);
50
+ }
51
+
52
+ .card-list-size-s {
53
+ --card-list-gap: 0.75rem;
54
+ --card-list-item-gap: 0.65rem;
55
+ --card-list-padding: 0.8rem;
56
+ --card-list-media-width: 26%;
57
+ --card-list-media-min-width: 5.5rem;
58
+ --card-list-top-media-width: 14rem;
59
+ --card-list-title-scale: 0.92;
60
+ --card-list-text-scale: 0.92;
61
+ }
62
+
63
+ .card-list-size-l {
64
+ --card-list-gap: clamp(1rem, 2.4vw, 1.5rem);
65
+ --card-list-item-gap: 1rem;
66
+ --card-list-padding: clamp(1.1rem, 2.4vw, 1.45rem);
67
+ --card-list-media-width: 36%;
68
+ --card-list-media-min-width: 8.5rem;
69
+ --card-list-top-media-width: 24rem;
70
+ --card-list-title-scale: 1.08;
71
+ --card-list-text-scale: 1.02;
72
+ }
73
+
74
+ .card-list-size-xl {
75
+ --card-list-gap: clamp(1.15rem, 2.8vw, 1.8rem);
76
+ --card-list-item-gap: 1.1rem;
77
+ --card-list-padding: clamp(1.25rem, 3vw, 1.75rem);
78
+ --card-list-media-width: 40%;
79
+ --card-list-media-min-width: 10rem;
80
+ --card-list-top-media-width: 28rem;
81
+ --card-list-title-scale: 1.18;
82
+ --card-list-text-scale: 1.06;
83
+ }
84
+
85
+ .card-list-flow-stack {
86
+ grid-template-columns: 1fr;
87
+ }
88
+
89
+ .card-list-item {
90
+ display: grid;
91
+ gap: var(--card-list-item-gap);
92
+ align-content: start;
93
+ margin: 0;
94
+ border: 1px solid color-mix(in srgb, currentColor 18%, transparent);
95
+ border-radius: var(--corner-radius-large, 8px);
96
+ padding: var(--card-list-padding);
97
+ background: var(--color-surface);
98
+ color: inherit;
99
+ }
100
+
101
+ .card-list-layout-image-left .card-list-item-has-image,
102
+ .card-list-layout-image-right .card-list-item-has-image {
103
+ grid-template-columns: minmax(var(--card-list-media-min-width), var(--card-list-media-width)) minmax(0, 1fr);
104
+ align-items: center;
105
+ }
106
+
107
+ .card-list-layout-image-right .card-list-item-has-image {
108
+ grid-template-columns: minmax(0, 1fr) minmax(var(--card-list-media-min-width), var(--card-list-media-width));
109
+ }
110
+
111
+ .card-list-layout-image-left .card-list-item-linked,
112
+ .card-list-layout-image-right .card-list-item-linked {
113
+ grid-template-columns: 1fr;
114
+ }
115
+
116
+ .card-list-layout-image-right .card-list-image-frame {
117
+ order: 2;
118
+ }
119
+
120
+ .card-list-link {
121
+ display: grid;
122
+ gap: var(--card-list-item-gap);
123
+ width: 100%;
124
+ color: inherit;
125
+ text-decoration: none;
126
+ }
127
+
128
+ .card-list-layout-image-left .card-list-item-has-image .card-list-link,
129
+ .card-list-layout-image-right .card-list-item-has-image .card-list-link {
130
+ grid-template-columns: minmax(var(--card-list-media-min-width), var(--card-list-media-width)) minmax(0, 1fr);
131
+ align-items: center;
132
+ }
133
+
134
+ .card-list-layout-image-right .card-list-item-has-image .card-list-link {
135
+ grid-template-columns: minmax(0, 1fr) minmax(var(--card-list-media-min-width), var(--card-list-media-width));
136
+ }
137
+
138
+ .card-list-link:hover .card-list-title,
139
+ .card-list-link:focus-visible .card-list-title {
140
+ text-decoration: underline;
141
+ text-underline-offset: 0.18em;
142
+ }
143
+
144
+ .card-list-image-frame {
145
+ display: grid;
146
+ width: 100%;
147
+ aspect-ratio: 16 / 10;
148
+ place-items: center;
149
+ overflow: hidden;
150
+ }
151
+
152
+ .card-list-flow-stack.card-list-layout-image-top .card-list-image-frame {
153
+ width: min(100%, var(--card-list-top-media-width));
154
+ }
155
+
156
+ .card-list-image {
157
+ display: block;
158
+ width: 100%;
159
+ height: 100%;
160
+ object-fit: contain;
161
+ }
162
+
163
+ .card-list-content {
164
+ display: grid;
165
+ gap: 0.4rem;
166
+ }
167
+
168
+ .card-list-badge {
169
+ justify-self: start;
170
+ margin: 0 0 0.15rem;
171
+ border: 1px solid color-mix(in srgb, currentColor 28%, transparent);
172
+ border-radius: 999px;
173
+ padding: 0.18rem 0.48rem;
174
+ background: color-mix(in srgb, currentColor 9%, transparent);
175
+ color: inherit;
176
+ font-size: calc(var(--section-body-font-size-desktop, 1rem) * 0.72);
177
+ font-weight: 700;
178
+ letter-spacing: 0;
179
+ line-height: 1.2;
180
+ }
181
+
182
+ .card-list-title {
183
+ margin: 0;
184
+ color: inherit;
185
+ font-size: calc(var(--section-markdown-h3-font-size-desktop, 1.1rem) * var(--card-list-title-scale));
186
+ font-weight: 700;
187
+ letter-spacing: 0;
188
+ line-height: var(--section-markdown-h3-line-height, 1.35);
189
+ text-transform: none;
190
+ }
191
+
192
+ .card-list-content p:not(.card-list-badge) {
193
+ margin: 0;
194
+ font-size: calc(var(--section-body-font-size-desktop, 1rem) * var(--card-list-text-scale));
195
+ line-height: var(--section-body-line-height, 1.5);
196
+ }
197
+
198
+ :is(.image-stack, .managed-images) {
199
+ display: grid;
200
+ gap: var(--space-image-item);
201
+ margin-top: 0;
202
+ }
203
+
204
+ :root[data-image-presentation='prose-aligned'] .section-body {
205
+ display: grid;
206
+ grid-template-columns: minmax(0, 1fr) minmax(0, var(--layout-reading-width)) minmax(0, 1fr);
207
+ }
208
+
209
+ :root[data-image-presentation='prose-aligned'] .section-body > * {
210
+ grid-column: 1 / -1;
211
+ }
212
+
213
+ :root[data-image-presentation='prose-aligned'] .section-body > :is(.image-stack, .managed-images) {
214
+ grid-column: 2 / -1;
215
+ min-width: 0;
216
+ }
217
+
218
+ @media (min-width: 701px) {
219
+ :root[data-image-presentation='prose-aligned'] .site-page-layout-tree .section-body {
220
+ grid-template-columns: minmax(0, var(--layout-reading-width)) minmax(0, 1fr);
221
+ }
222
+
223
+ :root[data-image-presentation='prose-aligned'] .site-page-layout-tree .section-body > :is(.image-stack, .managed-images) {
224
+ grid-column: 1 / -1;
225
+ }
226
+ }
227
+
228
+ .managed-image-item {
229
+ display: grid;
230
+ gap: 0.55rem;
231
+ align-content: start;
232
+ margin: 0;
233
+ }
234
+
235
+ .image-stack .managed-image-item {
236
+ width: var(--layout-stack-item-width);
237
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
238
+ }
239
+
240
+ .managed-image-frame {
241
+ display: grid;
242
+ width: var(--layout-media-width);
243
+ margin-block: 0;
244
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
245
+ background: transparent;
246
+ place-items: center;
247
+ }
248
+
249
+ .managed-image {
250
+ display: block;
251
+ width: auto;
252
+ margin: 0 auto;
253
+ background: transparent;
254
+ height: auto;
255
+ max-width: 100%;
256
+ max-height: var(--image-max-height);
257
+ object-fit: contain;
258
+ }
259
+
260
+ .managed-image.managed-image-landscape {
261
+ width: 100%;
262
+ max-height: none;
263
+ }
264
+
265
+ :root[data-image-presentation='prose-aligned'] .managed-image-frame {
266
+ margin-inline: 0 auto;
267
+ place-items: start;
268
+ }
269
+
270
+ :root[data-image-presentation='prose-aligned'] .managed-image {
271
+ margin-inline: 0 auto;
272
+ max-height: none;
273
+ }
274
+
275
+ :root[data-image-presentation='centered-fit'] .image-stack .managed-image-item,
276
+ :root[data-image-presentation='centered-fit'] .managed-image-frame {
277
+ margin-inline: auto;
278
+ }
279
+
280
+ .image-carousel {
281
+ position: relative;
282
+ --image-carousel-width-from-height: var(--image-carousel-width-from-height-desktop, var(--image-layout-width));
283
+ --layout-carousel-width: min(
284
+ 100%,
285
+ var(--layout-media-width),
286
+ var(--image-carousel-width-from-height, var(--image-layout-width))
287
+ );
288
+ --image-carousel-control-background: var(--color-control-background);
289
+ --image-carousel-control-background-active: var(--color-control-background-active);
290
+ --image-carousel-control-color: var(--color-control-text);
291
+ outline: none;
292
+ }
293
+
294
+ :root[data-image-presentation='prose-aligned'] .image-carousel {
295
+ --layout-carousel-width: min(100%, var(--layout-media-width));
296
+ }
297
+
298
+ .image-carousel:focus-visible {
299
+ outline: var(--focus-indicator-width) solid var(--color-focus-ring);
300
+ outline-offset: 0.5rem;
301
+ }
302
+
303
+ .image-carousel-slide {
304
+ flex: 0 0 100%;
305
+ min-width: 0;
306
+ margin: 0;
307
+ }
308
+
309
+ .image-carousel-stage {
310
+ position: relative;
311
+ display: grid;
312
+ width: var(--layout-carousel-width);
313
+ max-height: var(--image-max-height);
314
+ margin-block: 0;
315
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
316
+ aspect-ratio: var(--image-carousel-aspect-ratio, auto);
317
+ }
318
+
319
+ :root[data-image-presentation='prose-aligned'] .image-carousel-stage {
320
+ max-height: none;
321
+ margin-inline: 0 auto;
322
+ }
323
+
324
+ :root[data-image-presentation='centered-fit'] .image-carousel-stage {
325
+ margin-inline: auto;
326
+ }
327
+
328
+ .image-carousel-viewport {
329
+ height: 100%;
330
+ }
331
+
332
+ .image-carousel-frame {
333
+ display: grid;
334
+ width: 100%;
335
+ height: 100%;
336
+ min-height: 0;
337
+ place-items: center;
338
+ }
339
+
340
+ .image-carousel[data-carousel-ready='true'] .image-carousel-viewport {
341
+ overflow: hidden;
342
+ }
343
+
344
+ .image-carousel[data-carousel-ready='true'] .image-carousel-slides {
345
+ display: flex;
346
+ height: 100%;
347
+ touch-action: pan-y pinch-zoom;
348
+ }
349
+
350
+ .image-carousel[data-carousel-ready='true'] .image-carousel-slide {
351
+ display: grid;
352
+ height: 100%;
353
+ min-height: 0;
354
+ align-content: start;
355
+ }
356
+
357
+ .image-carousel-frame .managed-image {
358
+ width: 100%;
359
+ height: 100%;
360
+ min-width: 0;
361
+ min-height: 0;
362
+ max-width: 100%;
363
+ max-height: 100%;
364
+ object-fit: contain;
365
+ }
366
+
367
+ .image-carousel-button,
368
+ .image-carousel-position {
369
+ display: none;
370
+ }
371
+
372
+ .image-carousel[data-carousel-ready='true'] .image-carousel-button,
373
+ .image-carousel[data-carousel-ready='true'] .image-carousel-position {
374
+ display: grid;
375
+ }
376
+
377
+ .image-carousel-button {
378
+ position: absolute;
379
+ top: 50%;
380
+ z-index: 2;
381
+ width: 2.75rem;
382
+ height: 2.75rem;
383
+ padding: 0;
384
+ place-items: center;
385
+ border: 0;
386
+ border-radius: 999px;
387
+ background: var(--image-carousel-control-background);
388
+ box-shadow: 0 0.125rem 0.5rem rgb(0 0 0 / 18%);
389
+ color: var(--image-carousel-control-color);
390
+ cursor: pointer;
391
+ transform: translateY(-50%);
392
+ }
393
+
394
+ .image-carousel-button svg {
395
+ width: 1.5rem;
396
+ height: 1.5rem;
397
+ fill: none;
398
+ stroke: currentColor;
399
+ stroke-linecap: round;
400
+ stroke-linejoin: round;
401
+ stroke-width: 2;
402
+ }
403
+
404
+ .image-carousel-button:hover:not(:disabled),
405
+ .image-carousel-button:focus-visible:not(:disabled) {
406
+ background: var(--image-carousel-control-background-active);
407
+ }
408
+
409
+ .image-carousel-button:focus-visible:not(:disabled) {
410
+ outline: var(--focus-indicator-width) solid var(--image-carousel-control-color);
411
+ outline-offset: 2px;
412
+ box-shadow:
413
+ 0 0 0 4px var(--image-carousel-control-background-active),
414
+ 0 0 0 6px var(--color-focus-ring);
415
+ }
416
+
417
+ .image-carousel-button:disabled {
418
+ cursor: default;
419
+ opacity: 0;
420
+ pointer-events: none;
421
+ }
422
+
423
+ .image-carousel-button-previous {
424
+ left: 0.75rem;
425
+ }
426
+
427
+ .image-carousel-button-next {
428
+ right: 0.75rem;
429
+ }
430
+
431
+ .image-carousel-position {
432
+ position: absolute;
433
+ right: 0.75rem;
434
+ bottom: 0.75rem;
435
+ z-index: 2;
436
+ min-width: 3rem;
437
+ min-height: 1.875rem;
438
+ padding: 0.35rem 0.65rem;
439
+ place-items: center;
440
+ border: 0;
441
+ border-radius: 999px;
442
+ background: var(--image-carousel-control-background);
443
+ box-shadow: 0 0.125rem 0.5rem rgb(0 0 0 / 18%);
444
+ color: var(--image-carousel-control-color);
445
+ font-size: 0.8125rem;
446
+ font-variant-numeric: tabular-nums;
447
+ font-weight: 600;
448
+ line-height: 1;
449
+ text-align: center;
450
+ }
451
+
452
+ .image-carousel-captions {
453
+ width: min(var(--layout-carousel-width), 72ch);
454
+ margin-block: 0;
455
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
456
+ }
457
+
458
+ :root[data-image-presentation='prose-aligned'] .image-carousel-captions {
459
+ margin-inline: 0 auto;
460
+ }
461
+
462
+ :root[data-image-presentation='centered-fit'] .image-carousel-captions {
463
+ margin-inline: auto;
464
+ text-align: center;
465
+ }
466
+
467
+ :root[data-image-presentation='centered-fit'] .image-carousel-captions .image-details {
468
+ justify-content: center;
469
+ }
470
+
471
+ .image-carousel-caption {
472
+ margin-bottom: 0;
473
+ }
474
+
475
+ .image-carousel[data-carousel-ready='true'] .image-carousel-captions {
476
+ display: grid;
477
+ }
478
+
479
+ .image-carousel[data-carousel-ready='true'] .image-carousel-caption {
480
+ grid-area: 1 / 1;
481
+ visibility: hidden;
482
+ pointer-events: none;
483
+ }
484
+
485
+ .image-carousel[data-carousel-ready='true'] .image-carousel-caption.is-active {
486
+ visibility: visible;
487
+ pointer-events: auto;
488
+ }
489
+
490
+ .image-meta {
491
+ width: min(var(--layout-media-width), 72ch);
492
+ margin-block: var(--section-caption-spacing-before, 0.5em) 0;
493
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
494
+ font-size: var(--section-caption-font-size-desktop, 0.95rem);
495
+ text-align: var(--section-caption-align-desktop, center);
496
+ }
497
+
498
+ :root[data-image-presentation='prose-aligned'] .image-stack .image-meta {
499
+ margin-inline: 0 auto;
500
+ }
501
+
502
+ :root[data-image-presentation='centered-fit'] .image-stack .image-meta {
503
+ margin-inline: auto;
504
+ text-align: center;
505
+ }
506
+
507
+ :root[data-image-presentation='centered-fit'] .image-stack .image-details {
508
+ justify-content: center;
509
+ }
510
+
511
+ .image-details {
512
+ display: flex;
513
+ flex-wrap: wrap;
514
+ align-items: baseline;
515
+ justify-content: var(--section-caption-justify-desktop, center);
516
+ gap: 0.5rem;
517
+ margin-bottom: 0;
518
+ color: var(--section-secondary-text-color, var(--color-secondary-text));
519
+ font-size: inherit;
520
+ font-family: var(--font-sans);
521
+ letter-spacing: 0;
522
+ line-height: var(--section-caption-line-height, 1.5);
523
+ }