@janga/norna 0.7.0
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.
- package/LICENSE +674 -0
- package/README.md +109 -0
- package/astro.config.mjs +17 -0
- package/bin/norna.mjs +170 -0
- package/docs/README.md +48 -0
- package/docs/command-organization.md +402 -0
- package/docs/commands.md +152 -0
- package/docs/configuration.md +376 -0
- package/docs/content.md +384 -0
- package/docs/engine-development.md +164 -0
- package/docs/getting-started.md +96 -0
- package/docs/images-and-metadata.md +88 -0
- package/docs/local-development.md +61 -0
- package/docs/publishing.md +81 -0
- package/docs/site-examples-structure-note.md +105 -0
- package/docs/site-structure.md +81 -0
- package/fixtures/basic/site/.norna/generated-images.json +1 -0
- package/fixtures/basic/site/config.mjs +59 -0
- package/fixtures/basic/site/content.md +17 -0
- package/fixtures/basic/site/images/work/.gitkeep +1 -0
- package/fixtures/basic/site/public/robots.txt +2 -0
- package/fixtures/basic/site/theme.md +7 -0
- package/package.json +90 -0
- package/scripts/build-site.mjs +16 -0
- package/scripts/check-config.mjs +37 -0
- package/scripts/deploy-site.mjs +389 -0
- package/scripts/dev-local.mjs +313 -0
- package/scripts/doctor.mjs +38 -0
- package/scripts/engine-version.mjs +137 -0
- package/scripts/generate-images.mjs +369 -0
- package/scripts/init-site.mjs +249 -0
- package/scripts/lib/astro-command.mjs +34 -0
- package/scripts/lib/ci-lockfile.mjs +34 -0
- package/scripts/lib/image-dimensions.mjs +78 -0
- package/scripts/lib/presentation.mjs +72 -0
- package/scripts/lib/project-config.mjs +322 -0
- package/scripts/lib/run-command.mjs +21 -0
- package/scripts/lib/site-content.mjs +392 -0
- package/scripts/lib/site-paths.mjs +127 -0
- package/scripts/lib/typography.mjs +166 -0
- package/scripts/release.mjs +77 -0
- package/scripts/show-typography.mjs +210 -0
- package/scripts/sync-content-sections.mjs +610 -0
- package/scripts/sync-site-public.mjs +42 -0
- package/scripts/test-ci-lockfile.mjs +65 -0
- package/scripts/test-content-check.mjs +364 -0
- package/scripts/test-engine-commands.mjs +128 -0
- package/scripts/test-navigation-preview.mjs +108 -0
- package/scripts/test-navigation.mjs +116 -0
- package/scripts/test-package-check.mjs +394 -0
- package/scripts/test-site-public.mjs +85 -0
- package/scripts/test-temporary-visibility.mjs +99 -0
- package/scripts/update-engine.mjs +127 -0
- package/scripts/watch-pages-deploy.mjs +430 -0
- package/src/components/GalleryGrid.astro +221 -0
- package/src/components/SiteNavigation.astro +410 -0
- package/src/components/SitePage.astro +69 -0
- package/src/components/SiteSection.astro +174 -0
- package/src/content.config.ts +171 -0
- package/src/layouts/BaseLayout.astro +90 -0
- package/src/lib/generatedImages.ts +63 -0
- package/src/lib/sectionContent.ts +125 -0
- package/src/lib/sitePages.ts +80 -0
- package/src/lib/sitePublicAssets.ts +39 -0
- package/src/lib/visibility.ts +35 -0
- package/src/pages/[slug].astro +31 -0
- package/src/pages/index.astro +16 -0
- package/src/styles/global.css +872 -0
- package/starters/basic/.github/workflows/deploy.yml +65 -0
- package/starters/basic/README.md +55 -0
- package/starters/basic/package.json +35 -0
- package/starters/basic/site/config.mjs +60 -0
- package/starters/basic/site/content.md +21 -0
- package/starters/basic/site/images/work/.gitkeep +1 -0
- package/starters/basic/site/public/robots.txt +2 -0
- package/starters/basic/site/theme.md +53 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Technical site configuration lives in the selected site's `config.mjs`; by
|
|
4
|
+
default that is `site/config.mjs`. The file must default-export an object.
|
|
5
|
+
|
|
6
|
+
This document describes the generic configuration interface. It does not list
|
|
7
|
+
the current values for any one site.
|
|
8
|
+
|
|
9
|
+
## Site
|
|
10
|
+
|
|
11
|
+
### `site.url`
|
|
12
|
+
|
|
13
|
+
- Purpose: canonical public URL used in the page `<link rel="canonical">`,
|
|
14
|
+
deploy monitoring output, and site-specific documentation.
|
|
15
|
+
- Type: string.
|
|
16
|
+
- Required: yes.
|
|
17
|
+
- Default: none.
|
|
18
|
+
- Validation: non-empty absolute URL accepted by `new URL()`.
|
|
19
|
+
- Consequence: wrong values render a wrong canonical URL and make deploy output
|
|
20
|
+
point at the wrong site.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
site: {
|
|
26
|
+
url: 'https://example.com/',
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Layout
|
|
31
|
+
|
|
32
|
+
### `layout.pageWidth`
|
|
33
|
+
|
|
34
|
+
- Purpose: maximum width of the main page content area, including section
|
|
35
|
+
headings, section text, galleries, sticky-navigation alignment, and footer.
|
|
36
|
+
- Type: string containing a simple positive CSS length.
|
|
37
|
+
- Required: no.
|
|
38
|
+
- Default: `1180px`.
|
|
39
|
+
- Validation: if set, it must be a positive number followed by one of `px`,
|
|
40
|
+
`rem`, `em`, `vw`, `vh`, `vmin`, `vmax`, `ch`, or `%`.
|
|
41
|
+
- Consequence: the value overrides the global `--page-width` CSS variable.
|
|
42
|
+
It is the outer width limit for content that is centered on the page.
|
|
43
|
+
`gallery.width` cannot render wider than this page width or the available
|
|
44
|
+
viewport width after responsive gutters.
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
layout: {
|
|
50
|
+
pageWidth: '1180px',
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### `layout.gutter`
|
|
55
|
+
|
|
56
|
+
- Purpose: side margin removed from the viewport before the available content
|
|
57
|
+
width is calculated.
|
|
58
|
+
- Type: either a CSS length string used on all viewports, or an object with
|
|
59
|
+
`desktop` and `mobile` CSS length strings.
|
|
60
|
+
- Required: no.
|
|
61
|
+
- Default: desktop `clamp(1.25rem, 4vw, 3rem)`, mobile `1rem`.
|
|
62
|
+
- Validation: if set, each value must be a positive CSS length such as `16px`,
|
|
63
|
+
`3rem`, or `4vw`. `clamp()` with those simple lengths is also accepted.
|
|
64
|
+
- Consequence: wider gutters leave more side margin and reduce the maximum
|
|
65
|
+
available width for galleries and aligned text.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
layout: {
|
|
71
|
+
gutter: {
|
|
72
|
+
desktop: '48px',
|
|
73
|
+
mobile: '16px',
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Gallery
|
|
79
|
+
|
|
80
|
+
### `gallery.width`
|
|
81
|
+
|
|
82
|
+
- Purpose: maximum rendered width for gallery images, gallery captions, and
|
|
83
|
+
left- or right-aligned section text that is intended to line up with gallery
|
|
84
|
+
edges.
|
|
85
|
+
- Type: string containing a simple positive CSS length.
|
|
86
|
+
- Required: no.
|
|
87
|
+
- Default: `900px`.
|
|
88
|
+
- Validation: if set, it must be a positive number followed by one of `px`,
|
|
89
|
+
`rem`, `em`, `vw`, `vh`, `vmin`, `vmax`, `ch`, or `%`.
|
|
90
|
+
- Consequence: the value overrides the global `--gallery-width` CSS variable.
|
|
91
|
+
Images and aligned text cannot render wider than this value, but the
|
|
92
|
+
effective width is also limited by `layout.pageWidth`, `layout.gutter`, and
|
|
93
|
+
`gallery.maxAvailableWidthPercent`.
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
gallery: {
|
|
99
|
+
width: '900px',
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### `gallery.maxAvailableWidthPercent`
|
|
104
|
+
|
|
105
|
+
- Purpose: maximum share of the available width, after gutters, that gallery
|
|
106
|
+
images, gallery captions, and aligned section text may use.
|
|
107
|
+
- Type: either a number used on all viewports, or an object with `desktop` and
|
|
108
|
+
`mobile` numbers.
|
|
109
|
+
- Required: no.
|
|
110
|
+
- Default: desktop `100`, mobile `100`.
|
|
111
|
+
- Validation: each value must be greater than `0` and less than or equal to
|
|
112
|
+
`100`.
|
|
113
|
+
- Consequence: `100` allows the gallery to use the full available width. A
|
|
114
|
+
smaller value keeps galleries narrower without changing the page width or
|
|
115
|
+
gutters.
|
|
116
|
+
|
|
117
|
+
Example:
|
|
118
|
+
|
|
119
|
+
```js
|
|
120
|
+
gallery: {
|
|
121
|
+
maxAvailableWidthPercent: {
|
|
122
|
+
desktop: 100,
|
|
123
|
+
mobile: 100,
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `gallery.maxAvailableHeightPercent`
|
|
129
|
+
|
|
130
|
+
- Purpose: maximum share of viewport height that gallery images may use.
|
|
131
|
+
- Type: either a number used on all viewports, or an object with `desktop` and
|
|
132
|
+
`mobile` numbers.
|
|
133
|
+
- Required: no.
|
|
134
|
+
- Default: desktop `74`, mobile `68`.
|
|
135
|
+
- Validation: each value must be greater than `0` and less than or equal to
|
|
136
|
+
`100`.
|
|
137
|
+
- Consequence: images keep their proportions and are scaled down when filling
|
|
138
|
+
the available width would make them taller than this limit. This applies to
|
|
139
|
+
both landscape and portrait images.
|
|
140
|
+
|
|
141
|
+
Example:
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
gallery: {
|
|
145
|
+
maxAvailableHeightPercent: {
|
|
146
|
+
desktop: 74,
|
|
147
|
+
mobile: 68,
|
|
148
|
+
},
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Typography
|
|
153
|
+
|
|
154
|
+
### `typography.fontFamily`
|
|
155
|
+
|
|
156
|
+
- Purpose: global CSS `font-family` stack used by site text and sticky
|
|
157
|
+
navigation.
|
|
158
|
+
- Type: string containing a CSS font-family value.
|
|
159
|
+
- Required: no.
|
|
160
|
+
- Default: `Arial, 'Helvetica Neue', Helvetica, sans-serif`, matching the
|
|
161
|
+
engine's existing sticky-navigation font stack.
|
|
162
|
+
- Validation: if set, it must be a non-empty string and must not contain
|
|
163
|
+
semicolons, braces, or line breaks.
|
|
164
|
+
- Consequence: the value overrides the global `--font-sans` CSS variable for
|
|
165
|
+
the whole page. Section headings, body text, gallery captions, footer text,
|
|
166
|
+
and sticky navigation all inherit from that variable unless engine CSS gives a
|
|
167
|
+
more specific rule.
|
|
168
|
+
|
|
169
|
+
Example:
|
|
170
|
+
|
|
171
|
+
```js
|
|
172
|
+
typography: {
|
|
173
|
+
fontFamily: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Navigation
|
|
178
|
+
|
|
179
|
+
### `navigation.smoothScroll`
|
|
180
|
+
|
|
181
|
+
- Purpose: controls enhanced same-page anchor navigation and native
|
|
182
|
+
`scroll-behavior`.
|
|
183
|
+
- Type: object.
|
|
184
|
+
- Required: no; omitted fields use defaults.
|
|
185
|
+
|
|
186
|
+
Fields:
|
|
187
|
+
|
|
188
|
+
- `navigation.smoothScroll.enabled`: boolean, default `true`.
|
|
189
|
+
- `navigation.smoothScroll.minimumDurationMs`: positive integer, default
|
|
190
|
+
`2000`.
|
|
191
|
+
- `navigation.smoothScroll.maximumDurationMs`: positive integer, default
|
|
192
|
+
`4000`; must be greater than or equal to `minimumDurationMs`.
|
|
193
|
+
- `navigation.smoothScroll.durationPerPixelMs`: positive number, default
|
|
194
|
+
`0.22`.
|
|
195
|
+
|
|
196
|
+
When `enabled` is `false`, section links jump directly to anchors without the
|
|
197
|
+
controlled animation. The no-JavaScript fallback keeps real `href="#section-id"`
|
|
198
|
+
links.
|
|
199
|
+
|
|
200
|
+
Example:
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
navigation: {
|
|
204
|
+
smoothScroll: {
|
|
205
|
+
enabled: true,
|
|
206
|
+
minimumDurationMs: 600,
|
|
207
|
+
maximumDurationMs: 1_200,
|
|
208
|
+
durationPerPixelMs: 0.2,
|
|
209
|
+
},
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Locale And UI Labels
|
|
214
|
+
|
|
215
|
+
### `locale.lang`
|
|
216
|
+
|
|
217
|
+
- Purpose: language tag rendered on the root `<html lang="...">` element.
|
|
218
|
+
- Type: string language tag such as `en` or `sv`.
|
|
219
|
+
- Required: no.
|
|
220
|
+
- Default: `en`.
|
|
221
|
+
- Validation: two or three letters, optionally followed by `-` separated
|
|
222
|
+
subtags.
|
|
223
|
+
- Consequence: screen readers, browsers, and search engines use this to
|
|
224
|
+
interpret the page language.
|
|
225
|
+
|
|
226
|
+
### `locale.labels`
|
|
227
|
+
|
|
228
|
+
- Purpose: site-wide UI labels rendered by the engine for non-editorial
|
|
229
|
+
interface text.
|
|
230
|
+
- Type: object.
|
|
231
|
+
- Required: no; omitted labels use English defaults.
|
|
232
|
+
|
|
233
|
+
Fields:
|
|
234
|
+
|
|
235
|
+
- `locale.labels.skipToContent`: skip-link text, default `Skip to content`.
|
|
236
|
+
- `locale.labels.siteNavigation`: site-level navigation ARIA label and mobile
|
|
237
|
+
menu group heading, default `Pages`.
|
|
238
|
+
- `locale.labels.pageNavigation`: current-page section navigation ARIA label and
|
|
239
|
+
mobile menu group heading, default `On this page`.
|
|
240
|
+
- `locale.labels.sectionNavigation`: legacy section navigation label, default
|
|
241
|
+
`Sections`.
|
|
242
|
+
- `locale.labels.menu`: mobile menu summary text, default `Menu`.
|
|
243
|
+
- `locale.labels.closeMenu`: reserved close-menu label, default `Close menu`.
|
|
244
|
+
- `locale.labels.gallery`: gallery ARIA label prefix, default `Gallery`.
|
|
245
|
+
|
|
246
|
+
Example:
|
|
247
|
+
|
|
248
|
+
```js
|
|
249
|
+
locale: {
|
|
250
|
+
lang: 'sv',
|
|
251
|
+
labels: {
|
|
252
|
+
skipToContent: 'Hoppa till innehåll',
|
|
253
|
+
siteNavigation: 'Sidor',
|
|
254
|
+
pageNavigation: 'På denna sida',
|
|
255
|
+
sectionNavigation: 'Sektioner',
|
|
256
|
+
menu: 'Meny',
|
|
257
|
+
gallery: 'Galleri',
|
|
258
|
+
},
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Footer
|
|
263
|
+
|
|
264
|
+
### `footer.copyrightMessage`
|
|
265
|
+
|
|
266
|
+
- Purpose: optional footer sentence.
|
|
267
|
+
- Type: string.
|
|
268
|
+
- Required: no.
|
|
269
|
+
- Default: hidden.
|
|
270
|
+
- Validation: if set, it must be a non-empty string. `undefined`, `null`, and
|
|
271
|
+
`''` are treated as absent.
|
|
272
|
+
- Consequence: footer rendering is enabled when this or enabled build info is
|
|
273
|
+
present.
|
|
274
|
+
|
|
275
|
+
### `footer.buildInfo`
|
|
276
|
+
|
|
277
|
+
- Purpose: optional footer build timestamp.
|
|
278
|
+
- Type: object, `false`, `null`, or omitted.
|
|
279
|
+
- Required: no.
|
|
280
|
+
- Default: hidden.
|
|
281
|
+
- Validation: object fields are validated when the object is present. `false`,
|
|
282
|
+
`null`, or omission hides build info.
|
|
283
|
+
|
|
284
|
+
Fields:
|
|
285
|
+
|
|
286
|
+
- `footer.buildInfo.enabled`: boolean, default `true`.
|
|
287
|
+
- `footer.buildInfo.text`: required non-empty string.
|
|
288
|
+
- `footer.buildInfo.dateTimeFormat`: required object.
|
|
289
|
+
- `footer.buildInfo.dateTimeFormat.locale`: required string.
|
|
290
|
+
- `footer.buildInfo.dateTimeFormat.timeZone`: required string.
|
|
291
|
+
- `footer.buildInfo.dateTimeFormat.dateStyle`: required string.
|
|
292
|
+
- `footer.buildInfo.dateTimeFormat.timeStyle`: required string.
|
|
293
|
+
|
|
294
|
+
The date/time object must be accepted by `Intl.DateTimeFormat`.
|
|
295
|
+
|
|
296
|
+
Example:
|
|
297
|
+
|
|
298
|
+
```js
|
|
299
|
+
footer: {
|
|
300
|
+
copyrightMessage: '(c) Example Artist.',
|
|
301
|
+
buildInfo: {
|
|
302
|
+
enabled: true,
|
|
303
|
+
text: 'Built',
|
|
304
|
+
dateTimeFormat: {
|
|
305
|
+
locale: 'en-GB',
|
|
306
|
+
timeZone: 'UTC',
|
|
307
|
+
dateStyle: 'short',
|
|
308
|
+
timeStyle: 'short',
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
If both `footer.copyrightMessage` and enabled `footer.buildInfo` are absent, the
|
|
315
|
+
footer is not rendered.
|
|
316
|
+
|
|
317
|
+
## GitHub
|
|
318
|
+
|
|
319
|
+
### `github.repo`
|
|
320
|
+
|
|
321
|
+
- Purpose: repository used by deploy checks and deploy monitoring.
|
|
322
|
+
- Type: string in `owner/name` form.
|
|
323
|
+
- Required: yes.
|
|
324
|
+
- Default: none.
|
|
325
|
+
- Validation: non-empty string.
|
|
326
|
+
|
|
327
|
+
### `github.branch`
|
|
328
|
+
|
|
329
|
+
- Purpose: deploy branch required by `norna deploy` and monitored by
|
|
330
|
+
`deploy:watch`.
|
|
331
|
+
- Type: string.
|
|
332
|
+
- Required: yes.
|
|
333
|
+
- Default: none.
|
|
334
|
+
- Validation: non-empty string.
|
|
335
|
+
|
|
336
|
+
### `github.pagesWorkflow`
|
|
337
|
+
|
|
338
|
+
- Purpose: GitHub Actions workflow name used by deploy checks and
|
|
339
|
+
`deploy:watch`.
|
|
340
|
+
- Type: string.
|
|
341
|
+
- Required: yes.
|
|
342
|
+
- Default: none.
|
|
343
|
+
- Validation: non-empty string.
|
|
344
|
+
|
|
345
|
+
## Deploy Watch
|
|
346
|
+
|
|
347
|
+
### `deploy.watch`
|
|
348
|
+
|
|
349
|
+
- Purpose: defaults for `norna deploy:watch`.
|
|
350
|
+
- Type: object.
|
|
351
|
+
- Required: no; omitted fields use defaults.
|
|
352
|
+
|
|
353
|
+
Fields:
|
|
354
|
+
|
|
355
|
+
- `deploy.watch.intervalMs`: positive integer, default `10000`.
|
|
356
|
+
- `deploy.watch.timeoutMs`: positive integer, default `900000`.
|
|
357
|
+
- `deploy.watch.runLimit`: positive integer, default `10`.
|
|
358
|
+
|
|
359
|
+
Command-line options such as `--interval`, `--timeout`, and `--limit` can
|
|
360
|
+
override these values for one run.
|
|
361
|
+
|
|
362
|
+
## Site Directory Selection
|
|
363
|
+
|
|
364
|
+
The site directory is not configured in `config.mjs`.
|
|
365
|
+
|
|
366
|
+
Use one of:
|
|
367
|
+
|
|
368
|
+
```sh
|
|
369
|
+
NORNA_SITE_DIR=my-site npm run norna:build
|
|
370
|
+
norna --site-dir my-site build
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
If `NORNA_SITE_DIR` is set to an empty value, commands fail. Relative site
|
|
374
|
+
directories are resolved by walking upward from the invocation root until the
|
|
375
|
+
selected directory contains `config.mjs` and `content.md`. Absolute site
|
|
376
|
+
directories are accepted and make their parent the site project root.
|