@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,437 @@
1
+ /* Page frame, tree navigation, breadcrumbs, and shared layout coordinates. */
2
+
3
+ .site-content {
4
+ /* Shared coordinates keep prose and structured blocks on the same axis. */
5
+ --layout-inline-start-margin: auto;
6
+ --layout-inline-end-margin: auto;
7
+ --layout-stack-item-width: 100%;
8
+ position: relative;
9
+ z-index: 2;
10
+ width: min(calc(100% - (var(--content-gutter) * 2)), var(--page-width));
11
+ margin: 0 auto;
12
+ padding: 0;
13
+ }
14
+
15
+ .site-page-layout:not(.site-page-layout-tree) {
16
+ display: contents;
17
+ }
18
+
19
+ .site-page-layout-tree {
20
+ --tree-layout-width: max(var(--page-width), 86rem);
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;
24
+ --tree-layout-gap: var(--local-navigation-gap, clamp(1.5rem, 3vw, 3rem));
25
+ display: grid;
26
+ grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr) var(--contents-navigation-width);
27
+ align-items: start;
28
+ gap: var(--tree-layout-gap);
29
+ min-height: calc(100svh - var(--site-top-anchor-offset));
30
+ width: min(calc(100% - (var(--content-gutter) * 2)), var(--tree-layout-width));
31
+ margin: 0 auto;
32
+ }
33
+
34
+ .site-page-layout-tree > .site-content {
35
+ width: 100%;
36
+ min-width: 0;
37
+ }
38
+
39
+ .site-page-layout-tree .site-section {
40
+ background-color: transparent;
41
+ }
42
+
43
+ @media (min-width: 701px) {
44
+ .site-page-layout-tree > .site-content {
45
+ --layout-inline-start-margin: 0;
46
+ --layout-inline-end-margin: auto;
47
+ --layout-stack-item-width: min(100%, var(--image-layout-width));
48
+ }
49
+ }
50
+
51
+ .tree-local-navigation {
52
+ position: sticky;
53
+ top: calc(var(--site-top-anchor-offset) + 1.25rem);
54
+ z-index: 3;
55
+ min-height: 0;
56
+ max-height: calc(100svh - var(--site-top-anchor-offset) - 2.5rem);
57
+ border-inline-end: 1px solid var(--color-nav-separator);
58
+ padding: 1.5rem 0;
59
+ background: var(--color-page);
60
+ overflow-y: auto;
61
+ overscroll-behavior: contain;
62
+ }
63
+
64
+ .page-contents-navigation {
65
+ color: var(--color-secondary-text);
66
+ }
67
+
68
+ .page-contents-navigation-rail {
69
+ position: sticky;
70
+ top: calc(var(--site-top-anchor-offset) + 1.25rem);
71
+ z-index: 3;
72
+ min-height: 0;
73
+ max-height: calc(100svh - var(--site-top-anchor-offset) - 2.5rem);
74
+ border-inline-start: 1px solid var(--color-nav-separator);
75
+ padding: 1.5rem 0 1.5rem 1rem;
76
+ background: var(--color-page);
77
+ overflow-y: auto;
78
+ overscroll-behavior: contain;
79
+ }
80
+
81
+ .page-contents-navigation-inline {
82
+ display: none;
83
+ width: min(100%, var(--reader-text-width, var(--page-text-width, var(--text-width))));
84
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
85
+ border-block: 1px solid var(--color-nav-separator);
86
+ padding: 0.85rem 0;
87
+ }
88
+
89
+ .page-contents-navigation-label {
90
+ margin: 0 0 0.65rem;
91
+ color: var(--color-primary-text);
92
+ font-size: 0.7rem;
93
+ font-weight: 700;
94
+ letter-spacing: 0;
95
+ line-height: 1.3;
96
+ }
97
+
98
+ @media (min-width: 701px) and (max-width: 1100px) {
99
+ .site-page-layout-tree {
100
+ --tree-layout-width: max(var(--page-width), 76rem);
101
+ grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr);
102
+ }
103
+
104
+ .page-contents-navigation-rail {
105
+ display: none;
106
+ }
107
+
108
+ .page-contents-navigation-inline {
109
+ display: block;
110
+ }
111
+ }
112
+
113
+ .navigation-page-sections {
114
+ margin: 0.15rem 0 0.55rem 0.3rem;
115
+ border-left: 2px solid color-mix(in srgb, currentColor 38%, transparent);
116
+ padding: 0.2rem 0 0.25rem 0.85rem;
117
+ }
118
+
119
+ .navigation-page-tree,
120
+ .page-contents-links {
121
+ margin: 0;
122
+ padding: 0;
123
+ list-style: none;
124
+ }
125
+
126
+ .navigation-page-node {
127
+ position: relative;
128
+ }
129
+
130
+ .navigation-page-tree-sidebar .navigation-page-link {
131
+ display: block;
132
+ padding: 0.45rem 2rem 0.45rem 0;
133
+ color: var(--color-secondary-text);
134
+ font-size: 0.86rem;
135
+ line-height: 1.35;
136
+ text-decoration: none;
137
+ }
138
+
139
+ .navigation-page-tree-sidebar > .navigation-page-node > .navigation-page-link {
140
+ color: var(--color-primary-text);
141
+ font-size: 0.94rem;
142
+ font-weight: 700;
143
+ }
144
+
145
+ .navigation-page-tree-sidebar .navigation-page-link:hover,
146
+ .navigation-page-tree-sidebar .navigation-page-link:focus-visible,
147
+ .navigation-page-tree-sidebar .navigation-page-link[aria-current='page'] {
148
+ color: var(--color-primary-text);
149
+ text-decoration: underline;
150
+ text-decoration-thickness: 1px;
151
+ text-underline-offset: 0.28em;
152
+ }
153
+
154
+ .navigation-page-tree-sidebar .navigation-page-tree-sidebar {
155
+ margin: 0.25rem 0 0.25rem 0.3rem;
156
+ border-left: 1px solid color-mix(in srgb, currentColor 18%, transparent);
157
+ padding-left: 0.85rem;
158
+ }
159
+
160
+ .navigation-page-branch:not(.navigation-page-disclosure) > summary {
161
+ position: absolute;
162
+ top: 0.25rem;
163
+ right: 0;
164
+ display: grid;
165
+ place-items: center;
166
+ width: 1.8rem;
167
+ height: 1.8rem;
168
+ border: 0;
169
+ border-radius: var(--corner-radius-small, 2px);
170
+ list-style: none;
171
+ cursor: pointer;
172
+ color: var(--color-secondary-text);
173
+ }
174
+
175
+ .navigation-page-branch:not(.navigation-page-disclosure) > summary::-webkit-details-marker {
176
+ display: none;
177
+ }
178
+
179
+ .navigation-page-branch:not(.navigation-page-disclosure) > summary:hover,
180
+ .navigation-page-branch:not(.navigation-page-disclosure) > summary:focus-visible {
181
+ background: color-mix(in srgb, currentColor 8%, transparent);
182
+ color: var(--color-primary-text);
183
+ }
184
+
185
+ .navigation-page-branch:not(.navigation-page-disclosure) > summary > [aria-hidden='true']::before {
186
+ content: "+";
187
+ }
188
+
189
+ .navigation-page-branch:not(.navigation-page-disclosure)[open] > summary > [aria-hidden='true']::before {
190
+ content: "−";
191
+ }
192
+
193
+ .navigation-page-disclosure > .navigation-page-summary {
194
+ display: flex;
195
+ align-items: center;
196
+ justify-content: space-between;
197
+ width: 100%;
198
+ border: 0;
199
+ border-radius: var(--corner-radius-small, 2px);
200
+ padding: 0.45rem 0;
201
+ font-size: 0.86rem;
202
+ line-height: 1.35;
203
+ list-style: none;
204
+ cursor: pointer;
205
+ color: var(--color-secondary-text);
206
+ }
207
+
208
+ .navigation-page-disclosure > .navigation-page-summary > .navigation-page-summary-title {
209
+ min-width: 0;
210
+ width: calc(100% - 2rem);
211
+ overflow-wrap: anywhere;
212
+ }
213
+
214
+ .navigation-page-disclosure {
215
+ position: relative;
216
+ }
217
+
218
+ .navigation-page-disclosure-sidebar {
219
+ display: grid;
220
+ grid-template-columns: minmax(0, 1fr);
221
+ }
222
+
223
+ .navigation-page-disclosure-sidebar > .navigation-page-summary,
224
+ .navigation-page-disclosure-sidebar > .navigation-page-open-link {
225
+ grid-column: 1;
226
+ grid-row: 1;
227
+ }
228
+
229
+ .navigation-page-disclosure-sidebar > .navigation-page-open-link {
230
+ z-index: 1;
231
+ }
232
+
233
+ .navigation-page-disclosure-sidebar > .navigation-page-branch-content {
234
+ grid-column: 1;
235
+ grid-row: 2;
236
+ }
237
+
238
+ .navigation-page-disclosure > .navigation-page-summary::-webkit-details-marker {
239
+ display: none;
240
+ }
241
+
242
+ .navigation-page-disclosure > .navigation-page-summary:hover,
243
+ .navigation-page-disclosure > .navigation-page-summary:focus-visible,
244
+ .navigation-page-disclosure[data-current-page='true'] > .navigation-page-summary {
245
+ color: var(--color-primary-text);
246
+ }
247
+
248
+ .navigation-page-disclosure > .navigation-page-summary:hover > :first-child,
249
+ .navigation-page-disclosure > .navigation-page-summary:focus-visible > :first-child,
250
+ .navigation-page-disclosure[data-current-page='true'] > .navigation-page-summary > :first-child {
251
+ text-decoration: underline;
252
+ text-decoration-thickness: 1px;
253
+ text-underline-offset: 0.28em;
254
+ }
255
+
256
+ .navigation-page-disclosure:not(.navigation-category-disclosure)[open]
257
+ > .navigation-page-summary > .navigation-page-summary-title {
258
+ opacity: 0;
259
+ }
260
+
261
+ .navigation-category-disclosure[data-current-branch='true'] > .navigation-page-summary {
262
+ color: var(--color-primary-text);
263
+ }
264
+
265
+ .navigation-page-open-link {
266
+ position: absolute;
267
+ top: 0;
268
+ left: 0;
269
+ display: none;
270
+ width: calc(100% - 2rem);
271
+ padding: 0.45rem 0;
272
+ color: var(--color-secondary-text);
273
+ font-size: 0.86rem;
274
+ line-height: 1.35;
275
+ overflow: visible;
276
+ overflow-wrap: anywhere;
277
+ text-decoration: none;
278
+ white-space: normal;
279
+ }
280
+
281
+ .navigation-page-disclosure[open] > .navigation-page-open-link {
282
+ display: block;
283
+ }
284
+
285
+ .navigation-page-open-link:hover,
286
+ .navigation-page-open-link:focus-visible,
287
+ .navigation-page-open-link[aria-current='page'] {
288
+ color: var(--color-primary-text);
289
+ text-decoration: underline;
290
+ text-decoration-thickness: 1px;
291
+ text-underline-offset: 0.28em;
292
+ }
293
+
294
+ .navigation-page-chevron::before {
295
+ display: block;
296
+ content: "›";
297
+ font-size: 1.15rem;
298
+ line-height: 1;
299
+ transition: transform 140ms ease;
300
+ }
301
+
302
+ .navigation-page-disclosure[open] > .navigation-page-summary .navigation-page-chevron::before {
303
+ transform: rotate(90deg);
304
+ }
305
+
306
+ .navigation-page-tree-sidebar > .navigation-page-node > .navigation-page-disclosure > .navigation-page-summary {
307
+ color: var(--color-primary-text);
308
+ font-size: 0.94rem;
309
+ font-weight: 700;
310
+ }
311
+
312
+ .navigation-page-tree-sidebar > .navigation-page-node > .navigation-page-disclosure > .navigation-page-open-link {
313
+ color: var(--color-primary-text);
314
+ font-size: 0.94rem;
315
+ font-weight: 700;
316
+ }
317
+
318
+ .navigation-page-tree-sidebar .navigation-page-disclosure > .navigation-page-branch-content {
319
+ margin: 0.1rem 0 0.25rem 0.3rem;
320
+ border-left: 1px solid color-mix(in srgb, currentColor 18%, transparent);
321
+ padding-left: 0.85rem;
322
+ }
323
+
324
+ .navigation-page-tree-sidebar .navigation-page-disclosure .navigation-page-tree-sidebar {
325
+ margin: 0.25rem 0;
326
+ border-left: 0;
327
+ padding-left: 0;
328
+ }
329
+
330
+ .navigation-page-disclosure[data-current-branch='true']:not([data-current-page='true']):not([data-sections-open='true'])
331
+ > .navigation-page-branch-content > .navigation-page-sections {
332
+ display: none;
333
+ }
334
+
335
+ .page-contents-links li + li {
336
+ margin-top: 0.45rem;
337
+ }
338
+
339
+ .page-contents-links ol {
340
+ margin: 0.45rem 0 0;
341
+ padding-left: 0.8rem;
342
+ border-left: 1px solid color-mix(in srgb, currentColor 16%, transparent);
343
+ list-style: none;
344
+ }
345
+
346
+ .page-contents-links a {
347
+ position: relative;
348
+ display: block;
349
+ color: var(--color-secondary-text);
350
+ font-size: 0.8rem;
351
+ line-height: 1.4;
352
+ text-decoration: none;
353
+ }
354
+
355
+ .page-contents-links a:hover,
356
+ .page-contents-links a:focus-visible,
357
+ .page-contents-links a[aria-current='location'] {
358
+ color: var(--color-primary-text);
359
+ text-decoration: underline;
360
+ text-underline-offset: 0.25em;
361
+ }
362
+
363
+ .page-contents-links a[aria-current='location']::before {
364
+ position: absolute;
365
+ top: 0.15em;
366
+ bottom: 0.15em;
367
+ left: -0.85rem;
368
+ width: 2px;
369
+ border-radius: 1px;
370
+ background: currentColor;
371
+ content: '';
372
+ }
373
+
374
+ .site-breadcrumbs {
375
+ min-height: calc(clamp(1rem, 2.5vw, 1.5rem) + 1.35rem);
376
+ width: min(100%, var(--reader-text-width, var(--page-text-width, var(--text-width))));
377
+ margin-block: 0;
378
+ margin-inline: var(--layout-inline-start-margin) var(--layout-inline-end-margin);
379
+ padding-top: clamp(1rem, 2.5vw, 1.5rem);
380
+ font-size: 1rem;
381
+ line-height: 1.4;
382
+ overflow: visible;
383
+ }
384
+
385
+ .site-breadcrumbs ol {
386
+ display: flex;
387
+ flex-wrap: wrap;
388
+ gap: 0;
389
+ margin: 0;
390
+ padding: 0;
391
+ font-size: 0.78rem;
392
+ list-style: none;
393
+ }
394
+
395
+ .site-breadcrumbs li {
396
+ display: flex;
397
+ min-width: 0;
398
+ align-items: center;
399
+ }
400
+
401
+ .site-breadcrumbs li:last-child {
402
+ flex: 0 1 auto;
403
+ }
404
+
405
+ .site-breadcrumbs li + li::before {
406
+ margin: 0 0.55rem;
407
+ content: "/";
408
+ opacity: 0.38;
409
+ }
410
+
411
+ .site-breadcrumbs a {
412
+ display: block;
413
+ min-width: 0;
414
+ color: var(--color-secondary-text);
415
+ overflow: visible;
416
+ overflow-wrap: anywhere;
417
+ text-decoration: none;
418
+ }
419
+
420
+ .site-breadcrumbs a:hover,
421
+ .site-breadcrumbs a:focus-visible {
422
+ color: var(--color-primary-text);
423
+ text-decoration: underline;
424
+ text-underline-offset: 0.25em;
425
+ }
426
+
427
+ .site-breadcrumbs [aria-current='page'] {
428
+ display: block;
429
+ min-width: 0;
430
+ overflow: visible;
431
+ overflow-wrap: anywhere;
432
+ font-weight: 650;
433
+ }
434
+
435
+ .site-content-has-breadcrumbs > .site-section:first-of-type {
436
+ padding-top: clamp(1.15rem, 2.5vw, 1.75rem);
437
+ }