@janga/norna 0.7.3 → 0.7.4
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/docs/README.md +3 -3
- package/docs/commands.md +2 -2
- package/docs/configuration.md +2 -1
- package/docs/design/command-organization.md +4 -3
- package/docs/design/site-examples-structure.md +4 -3
- package/docs/getting-started.md +8 -7
- package/docs/theme.md +27 -43
- package/docs/typography.md +47 -31
- package/examples/dog-gallery/site/content.md +1 -1
- package/examples/dog-gallery/site/theme.md +12 -14
- package/package.json +1 -1
- package/scripts/check-config.mjs +1 -0
- package/scripts/lib/project-config.mjs +87 -32
- package/scripts/lib/site-content.mjs +4 -4
- package/scripts/lib/typography.mjs +79 -39
- package/scripts/show-typography.mjs +75 -11
- package/scripts/test-engine-commands.mjs +18 -0
- package/scripts/test-package-check.mjs +19 -3
- package/src/components/SiteSection.astro +82 -20
- package/src/content.config.ts +11 -9
- package/src/layouts/BaseLayout.astro +0 -6
- package/src/styles/global.css +44 -17
- package/starters/basic/README.md +4 -3
- package/starters/basic/site/theme.md +19 -46
- package/starters/project/README.md +7 -7
- package/starters/project/package-lock.json +4 -4
- package/starters/project/package.json +1 -1
- package/starters/project/site/content.md +86 -46
- package/starters/project/site/routes/guide/route-content.md +52 -25
- package/starters/project/site/theme.md +29 -1
- package/examples/dog-gallery/.astro/collections/site.schema.json +0 -802
- package/examples/dog-gallery/.astro/collections/theme.schema.json +0 -714
- package/examples/dog-gallery/.astro/content-assets.mjs +0 -4
- package/examples/dog-gallery/.astro/content-modules.mjs +0 -1
- package/examples/dog-gallery/.astro/content.d.ts +0 -175
- package/examples/dog-gallery/.astro/data-store.json +0 -1
- package/examples/dog-gallery/.astro/dev-local.json +0 -8
- package/examples/dog-gallery/.astro/dev.json +0 -13
- package/examples/dog-gallery/.astro/dev.log +0 -49
- package/examples/dog-gallery/.astro/settings.json +0 -5
- package/examples/dog-gallery/.astro/types.d.ts +0 -2
- package/examples/dog-gallery/dist/_astro/GalleryGrid.astro_astro_type_script_index_0_lang.B0kxDyGz.js +0 -1
- package/examples/dog-gallery/dist/_astro/SitePage.BFHZm5UG.css +0 -1
- package/examples/dog-gallery/dist/dog-care/index.html +0 -15
- package/examples/dog-gallery/dist/favicon.svg +0 -7
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-1536.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/black-puppy-meadow-7255e3d9-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/black-dogs/photo-of-a-black-dog-5cf614d2-960.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-3939.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/brown-dog-50ef114e-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-2400.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/brown-dogs/dog-accompanies-master-7ef804d5-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-1600.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/golden-retriever-f797fd88-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-1920.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-2576.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/golden-dogs/toller-puppy-a2a8fbc0-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-1277.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-cute-dog-077a0689-768.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1080.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1440.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-1536.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-480.webp +0 -0
- package/examples/dog-gallery/dist/images/generated/white-dogs/white-puppy-garden-d3ab2ca0-768.webp +0 -0
- package/examples/dog-gallery/dist/index.html +0 -43
- package/examples/dog-gallery/dist/robots.txt +0 -2
package/docs/README.md
CHANGED
|
@@ -41,9 +41,9 @@ For a quick reference:
|
|
|
41
41
|
- [Content](content.md) describes page frontmatter, section frontmatter,
|
|
42
42
|
image rows, carousels, temporary sections, Markdown section matching, and
|
|
43
43
|
content validation.
|
|
44
|
-
- [Theme](theme.md) describes site-wide layout,
|
|
45
|
-
typography, presentation colors, frame colors, and inline styles.
|
|
46
|
-
- [Typography](typography.md) describes presets, roles, overrides,
|
|
44
|
+
- [Theme](theme.md) describes site-wide layout, layout density, image sizing,
|
|
45
|
+
font, typography rhythm, presentation colors, frame colors, and inline styles.
|
|
46
|
+
- [Typography](typography.md) describes presets, rhythms, roles, overrides,
|
|
47
47
|
inheritance, and inspection commands.
|
|
48
48
|
- [Routes](routes.md) describes route files, slugs, route navigation, and
|
|
49
49
|
route image directories.
|
package/docs/commands.md
CHANGED
|
@@ -105,8 +105,8 @@ should normally mean the repository's complete publishable artifact, while
|
|
|
105
105
|
runs `astro sync`.
|
|
106
106
|
- `content:sync` / `norna:sync`: rewrites Markdown section order and moves misplaced referenced
|
|
107
107
|
image files after confirmation.
|
|
108
|
-
- `typography presets`: prints the exact built-in values for
|
|
109
|
-
|
|
108
|
+
- `typography presets`: prints the exact built-in values for typography
|
|
109
|
+
presets and rhythms.
|
|
110
110
|
- `typography show`: prints the selected site's resolved typography for the
|
|
111
111
|
theme, every page route, and every section. Each value includes its source,
|
|
112
112
|
and inherited page or section values are marked with `inherited: true`.
|
package/docs/configuration.md
CHANGED
|
@@ -66,11 +66,12 @@ Use [Theme](theme.md) for:
|
|
|
66
66
|
|
|
67
67
|
- `layout.pageWidth`
|
|
68
68
|
- `layout.gutter`
|
|
69
|
+
- `layout.density`
|
|
69
70
|
- `gallery.width`
|
|
70
71
|
- `gallery.maxAvailableWidthPercent`
|
|
71
72
|
- `gallery.maxAvailableHeightPercent`
|
|
72
73
|
- `typography.fontFamily`
|
|
73
|
-
- typography presets and overrides
|
|
74
|
+
- typography presets, rhythm, and overrides
|
|
74
75
|
- presentation colors, inline styles, and frame colors
|
|
75
76
|
|
|
76
77
|
## Navigation
|
|
@@ -275,9 +275,10 @@ npm run norna:typography:presets
|
|
|
275
275
|
npm run norna:typography:show
|
|
276
276
|
```
|
|
277
277
|
|
|
278
|
-
`norna:typography:presets` shows the built-in typography presets
|
|
279
|
-
installed engine. `norna:typography:show` shows the effective
|
|
280
|
-
the selected site after presets and overrides have
|
|
278
|
+
`norna:typography:presets` shows the built-in typography presets and rhythms
|
|
279
|
+
from the installed engine. `norna:typography:show` shows the effective
|
|
280
|
+
typography for the selected site after presets, rhythms, and overrides have
|
|
281
|
+
been applied.
|
|
281
282
|
|
|
282
283
|
### Correct Content And Configuration
|
|
283
284
|
|
|
@@ -26,8 +26,8 @@ site repository. It should not be a showcase for every feature.
|
|
|
26
26
|
An example site is a runnable site that demonstrates one or more features.
|
|
27
27
|
|
|
28
28
|
Examples can be richer than the starter. They may show routes, navigation,
|
|
29
|
-
typography presets, galleries, image carousels, inline
|
|
30
|
-
configuration choices.
|
|
29
|
+
typography presets, typography rhythms, galleries, image carousels, inline
|
|
30
|
+
styles, and site-specific configuration choices.
|
|
31
31
|
|
|
32
32
|
### Documentation Site
|
|
33
33
|
|
|
@@ -72,7 +72,8 @@ they demonstrate a distinct feature or workflow.
|
|
|
72
72
|
navigation diagnostic target.
|
|
73
73
|
- `routes-demo/`: focused route/navigation example if the dog example becomes
|
|
74
74
|
too broad.
|
|
75
|
-
- `typography-demo/`: focused typography preset and override example
|
|
75
|
+
- `typography-demo/`: focused typography preset, rhythm, and override example
|
|
76
|
+
if needed.
|
|
76
77
|
|
|
77
78
|
The repository-local `site/` directory is reserved for the documentation site.
|
|
78
79
|
`docs/` should remain for reference documentation. It should link to the
|
package/docs/getting-started.md
CHANGED
|
@@ -64,9 +64,9 @@ Commit the generated `package-lock.json` after the first install.
|
|
|
64
64
|
|
|
65
65
|
1. Edit `site/config.mjs` for the site's URL, language labels, GitHub
|
|
66
66
|
repository, footer, and deploy settings.
|
|
67
|
-
2. Edit `site/theme.md` for site-wide layout,
|
|
68
|
-
font, typography preset, colors, inline styles, and
|
|
69
|
-
to use engine defaults.
|
|
67
|
+
2. Edit `site/theme.md` for site-wide layout, layout density, typography
|
|
68
|
+
rhythm, image sizing, font, typography preset, colors, inline styles, and
|
|
69
|
+
frame colors, or omit it to use engine defaults.
|
|
70
70
|
3. Edit `site/content.md` for homepage title, description, sections, text,
|
|
71
71
|
image rows, page/section presentation overrides, alt text, and captions.
|
|
72
72
|
4. Put source images under `site/images/<section-id>/`.
|
|
@@ -114,12 +114,13 @@ Read [Site Structure](site-structure.md), [Content](content.md),
|
|
|
114
114
|
[Theme](theme.md), [Typography](typography.md), [Routes](routes.md), and
|
|
115
115
|
[Configuration](configuration.md) before publishing a real site.
|
|
116
116
|
|
|
117
|
-
To change the site's maximum page width, side gutters,
|
|
118
|
-
width, image height limits, font, colors, or
|
|
119
|
-
`site/theme.md`. See [Theme](theme.md) for
|
|
117
|
+
To change the site's maximum page width, side gutters, layout density,
|
|
118
|
+
typography rhythm, image width, image height limits, font, colors, or
|
|
119
|
+
site-wide typography preset, edit `site/theme.md`. See [Theme](theme.md) for
|
|
120
|
+
the accepted shape.
|
|
120
121
|
|
|
121
122
|
To change one page or section, add a focused `presentation.typography`
|
|
122
123
|
override in `site/content.md`. See [Typography](typography.md). Use
|
|
123
|
-
`norna typography presets` to inspect the installed preset values and
|
|
124
|
+
`norna typography presets` to inspect the installed preset and rhythm values and
|
|
124
125
|
`norna typography show` to inspect the resolved typography for the selected
|
|
125
126
|
site.
|
package/docs/theme.md
CHANGED
|
@@ -15,35 +15,11 @@ on top of the resolved page presentation.
|
|
|
15
15
|
navigation:
|
|
16
16
|
brand: Example Site
|
|
17
17
|
layout:
|
|
18
|
+
density: normal
|
|
18
19
|
pageWidth: 1180px
|
|
19
20
|
gutter:
|
|
20
21
|
desktop: clamp(1.25rem, 4vw, 3rem)
|
|
21
22
|
mobile: 1rem
|
|
22
|
-
spacing:
|
|
23
|
-
firstSectionTop:
|
|
24
|
-
desktop: clamp(1.875rem, 3vw, 2.75rem)
|
|
25
|
-
mobile: 1.375rem
|
|
26
|
-
sectionGap:
|
|
27
|
-
desktop: clamp(2.55rem, 4.2vw, 3.9rem)
|
|
28
|
-
mobile: 2.25rem
|
|
29
|
-
finalSectionBottom:
|
|
30
|
-
desktop: clamp(2.55rem, 4.2vw, 3.9rem)
|
|
31
|
-
mobile: 2.25rem
|
|
32
|
-
sectionHeadingToBody:
|
|
33
|
-
desktop: clamp(0.5625rem, 1.25vw, 0.75rem)
|
|
34
|
-
mobile: 0.4375rem
|
|
35
|
-
bodyToImages:
|
|
36
|
-
desktop: clamp(1.25rem, 2.5vw, 2rem)
|
|
37
|
-
mobile: 1.25rem
|
|
38
|
-
imageGap:
|
|
39
|
-
desktop: clamp(1.5rem, 3.5vw, 2.75rem)
|
|
40
|
-
mobile: 2.75rem
|
|
41
|
-
subheadingTop:
|
|
42
|
-
desktop: 2rem
|
|
43
|
-
mobile: 1.6rem
|
|
44
|
-
subheadingRuleTop:
|
|
45
|
-
desktop: 1rem
|
|
46
|
-
mobile: 0.8rem
|
|
47
23
|
gallery:
|
|
48
24
|
width: 900px
|
|
49
25
|
maxAvailableWidthPercent:
|
|
@@ -55,6 +31,7 @@ gallery:
|
|
|
55
31
|
typography:
|
|
56
32
|
fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
|
|
57
33
|
preset: quiet-gallery
|
|
34
|
+
rhythm: normal
|
|
58
35
|
presentation:
|
|
59
36
|
backgroundColor: "#000000"
|
|
60
37
|
textColor: "#f7f4ee"
|
|
@@ -94,14 +71,17 @@ navigation:
|
|
|
94
71
|
- `gutter`: side margin removed from the viewport before available content
|
|
95
72
|
width is calculated. Use either one CSS length for all viewports or
|
|
96
73
|
`desktop` / `mobile` values.
|
|
97
|
-
- `
|
|
98
|
-
|
|
99
|
-
|
|
74
|
+
- `density`: default structural spacing profile. Allowed values are `compact`,
|
|
75
|
+
`normal`, and `airy`.
|
|
76
|
+
- `spacing`: optional structural spacing overrides for sections and image
|
|
77
|
+
rows. Every spacing value accepts either one CSS length for all viewports or
|
|
78
|
+
`desktop` / `mobile` values.
|
|
100
79
|
|
|
101
80
|
Example:
|
|
102
81
|
|
|
103
82
|
```yaml
|
|
104
83
|
layout:
|
|
84
|
+
density: normal
|
|
105
85
|
pageWidth: 1180px
|
|
106
86
|
gutter:
|
|
107
87
|
desktop: clamp(1.25rem, 4vw, 3rem)
|
|
@@ -111,28 +91,25 @@ layout:
|
|
|
111
91
|
desktop: clamp(1.875rem, 3vw, 2.75rem)
|
|
112
92
|
mobile: 1.375rem
|
|
113
93
|
sectionGap:
|
|
114
|
-
desktop: clamp(
|
|
115
|
-
mobile:
|
|
116
|
-
subheadingTop:
|
|
117
|
-
desktop: 2rem
|
|
118
|
-
mobile: 1.6rem
|
|
94
|
+
desktop: clamp(1.4rem, 3vw, 2.75rem)
|
|
95
|
+
mobile: 1.5rem
|
|
119
96
|
```
|
|
120
97
|
|
|
121
98
|
If omitted, Norna uses `1180px` for `pageWidth`, desktop
|
|
122
|
-
`clamp(1.25rem, 4vw, 3rem)` for `gutter`, mobile `1rem`, and
|
|
123
|
-
|
|
99
|
+
`clamp(1.25rem, 4vw, 3rem)` for `gutter`, mobile `1rem`, and `normal` layout
|
|
100
|
+
density.
|
|
124
101
|
|
|
125
102
|
Spacing keys:
|
|
126
103
|
|
|
127
104
|
- `firstSectionTop`: space above the first section heading.
|
|
128
105
|
- `sectionGap`: space above each following section.
|
|
129
106
|
- `finalSectionBottom`: space below the final section.
|
|
130
|
-
- `sectionHeadingToBody`: space from a section heading to its body text.
|
|
131
107
|
- `bodyToImages`: space from section body text to image rows.
|
|
132
108
|
- `imageGap`: space between image rows.
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
109
|
+
|
|
110
|
+
Text-near spacing, such as spacing after headings, spacing before Markdown
|
|
111
|
+
subheadings, paragraph spacing, and caption spacing, belongs to
|
|
112
|
+
`typography.rhythm` and typography overrides.
|
|
136
113
|
|
|
137
114
|
## Image Sizing
|
|
138
115
|
|
|
@@ -166,6 +143,8 @@ Top-level `typography` is the site-wide typographic base. It supports:
|
|
|
166
143
|
|
|
167
144
|
- `fontFamily`: global CSS font-family stack.
|
|
168
145
|
- `preset`: built-in typography preset.
|
|
146
|
+
- `rhythm`: text-near spacing profile. Allowed values are `compact`,
|
|
147
|
+
`normal`, and `airy`.
|
|
169
148
|
- `overrides`: focused changes to preset values.
|
|
170
149
|
|
|
171
150
|
Example:
|
|
@@ -174,19 +153,23 @@ Example:
|
|
|
174
153
|
typography:
|
|
175
154
|
fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
|
|
176
155
|
preset: quiet-gallery
|
|
156
|
+
rhythm: normal
|
|
177
157
|
overrides:
|
|
178
158
|
headings:
|
|
179
159
|
h2:
|
|
180
160
|
size: medium
|
|
161
|
+
spacingAfter: 0.55em
|
|
181
162
|
h3:
|
|
182
|
-
size:
|
|
163
|
+
size: medium
|
|
164
|
+
spacingBefore: 1.5em
|
|
165
|
+
spacingAfter: 0.5em
|
|
183
166
|
body:
|
|
184
167
|
lineHeight: 1.55
|
|
185
168
|
```
|
|
186
169
|
|
|
187
|
-
Use `norna typography presets` to inspect built-in preset values
|
|
188
|
-
`norna typography show` to inspect the resolved typography for the
|
|
189
|
-
site. See [Typography](typography.md).
|
|
170
|
+
Use `norna typography presets` to inspect built-in preset and rhythm values,
|
|
171
|
+
and `norna typography show` to inspect the resolved typography for the
|
|
172
|
+
selected site. See [Typography](typography.md).
|
|
190
173
|
|
|
191
174
|
## Presentation
|
|
192
175
|
|
|
@@ -218,6 +201,7 @@ presentation:
|
|
|
218
201
|
headings:
|
|
219
202
|
h2:
|
|
220
203
|
size: large
|
|
204
|
+
spacingAfter: 0.6em
|
|
221
205
|
body:
|
|
222
206
|
paragraphSpacing: 1em
|
|
223
207
|
```
|
package/docs/typography.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Typography
|
|
2
2
|
|
|
3
3
|
`norna` typography is configured in `site/theme.md` through a site-wide font,
|
|
4
|
-
presets, and optional overrides.
|
|
4
|
+
presets, text rhythm, and optional overrides.
|
|
5
5
|
|
|
6
|
-
The normal place to choose a site-wide typography preset is the
|
|
7
|
-
`typography` block in `site/theme.md`.
|
|
6
|
+
The normal place to choose a site-wide typography preset and rhythm is the
|
|
7
|
+
top-level `typography` block in `site/theme.md`.
|
|
8
8
|
Page and section files may override the theme when a page or section needs a
|
|
9
9
|
different presentation.
|
|
10
10
|
|
|
@@ -18,25 +18,31 @@ Available presets:
|
|
|
18
18
|
short information blocks.
|
|
19
19
|
- `text-forward`: more generous body text for pages where longer text carries
|
|
20
20
|
more of the experience.
|
|
21
|
-
- `statement`:
|
|
22
|
-
programmatic statements. Use it sparingly, usually as a
|
|
21
|
+
- `statement`: tighter, more declarative line-height for introductions, first
|
|
22
|
+
sections, and short programmatic statements. Use it sparingly, usually as a
|
|
23
|
+
section override.
|
|
23
24
|
|
|
24
25
|
If theme typography is omitted, `quiet-gallery` is used.
|
|
25
26
|
|
|
26
|
-
Presets define `headings.h1` through
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
Presets define alignment, size, and line height for `headings.h1` through
|
|
28
|
+
`headings.h4`, `body`, and `caption`. Built-in presets use `medium` as the
|
|
29
|
+
default size for every text role. Visual heading hierarchy comes from the
|
|
30
|
+
Markdown heading level, so `h1` is larger than `h2`, `h2` is larger than `h3`,
|
|
31
|
+
and so on.
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
`rhythm` defines text-near spacing for headings, paragraphs, and captions.
|
|
34
|
+
Available rhythms are `compact`, `normal`, and `airy`. Built-in rhythm values
|
|
35
|
+
use `em` so spacing follows the rendered text size.
|
|
36
|
+
|
|
37
|
+
Use this command to inspect the exact preset and rhythm values shipped with
|
|
38
|
+
the installed engine:
|
|
33
39
|
|
|
34
40
|
```sh
|
|
35
41
|
norna typography presets
|
|
36
42
|
```
|
|
37
43
|
|
|
38
44
|
Use this command to inspect the effective values for the selected site after
|
|
39
|
-
presets and overrides have been applied:
|
|
45
|
+
presets, rhythms, and overrides have been applied:
|
|
40
46
|
|
|
41
47
|
```sh
|
|
42
48
|
norna typography show
|
|
@@ -52,14 +58,20 @@ also marked with `inherited: true`.
|
|
|
52
58
|
typography:
|
|
53
59
|
fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
|
|
54
60
|
preset: quiet-gallery
|
|
61
|
+
rhythm: normal
|
|
55
62
|
overrides:
|
|
56
63
|
headings:
|
|
57
64
|
h2:
|
|
58
65
|
size: medium
|
|
66
|
+
spacingAfter: 0.55em
|
|
59
67
|
h3:
|
|
60
|
-
size:
|
|
68
|
+
size: medium
|
|
69
|
+
spacingBefore: 1.5em
|
|
70
|
+
spacingAfter: 0.5em
|
|
61
71
|
body:
|
|
62
72
|
paragraphSpacing: 0.8em
|
|
73
|
+
caption:
|
|
74
|
+
spacingBefore: 0.5em
|
|
63
75
|
```
|
|
64
76
|
|
|
65
77
|
The typographic roles are:
|
|
@@ -84,27 +96,28 @@ align:
|
|
|
84
96
|
Allowed size values are `small`, `medium`, `large`, and `xlarge`. `medium` is
|
|
85
97
|
the normal reading size. Use `small` for quieter supporting text, and use
|
|
86
98
|
`large` or `xlarge` only when a page or section needs stronger emphasis.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
`headings.h2`.
|
|
99
|
+
Each heading level uses its own scale, but follows the same principle:
|
|
100
|
+
`medium` is the normal size for that level. Norna may render the first section
|
|
101
|
+
heading as an HTML `h1` for document structure, but its visual typography still
|
|
102
|
+
follows the Markdown level the user wrote: `##` uses `headings.h2`.
|
|
92
103
|
|
|
93
|
-
`lineHeight` is a unitless number from `1` through `3`. `
|
|
94
|
-
`paragraphSpacing` are CSS lengths such as `0`, `0.8em`,
|
|
104
|
+
`lineHeight` is a unitless number from `1` through `3`. `spacingBefore`,
|
|
105
|
+
`spacingAfter`, and `paragraphSpacing` are CSS lengths such as `0`, `0.8em`,
|
|
106
|
+
`1rem`, or `12px`. Use `em` for spacing that should track the text size.
|
|
95
107
|
|
|
96
108
|
Supported override fields:
|
|
97
109
|
|
|
98
110
|
- `headings.h1.align`, `headings.h1.size`, `headings.h1.lineHeight`,
|
|
99
|
-
`headings.h1.
|
|
111
|
+
`headings.h1.spacingBefore`, `headings.h1.spacingAfter`
|
|
100
112
|
- `headings.h2.align`, `headings.h2.size`, `headings.h2.lineHeight`,
|
|
101
|
-
`headings.h2.
|
|
113
|
+
`headings.h2.spacingBefore`, `headings.h2.spacingAfter`
|
|
102
114
|
- `headings.h3.align`, `headings.h3.size`, `headings.h3.lineHeight`,
|
|
103
|
-
`headings.h3.
|
|
115
|
+
`headings.h3.spacingBefore`, `headings.h3.spacingAfter`
|
|
104
116
|
- `headings.h4.align`, `headings.h4.size`, `headings.h4.lineHeight`,
|
|
105
|
-
`headings.h4.
|
|
117
|
+
`headings.h4.spacingBefore`, `headings.h4.spacingAfter`
|
|
106
118
|
- `body.align`, `body.size`, `body.lineHeight`, `body.paragraphSpacing`
|
|
107
|
-
- `caption.align`, `caption.size`, `caption.lineHeight`,
|
|
119
|
+
- `caption.align`, `caption.size`, `caption.lineHeight`,
|
|
120
|
+
`caption.spacingBefore`
|
|
108
121
|
|
|
109
122
|
## Inheritance
|
|
110
123
|
|
|
@@ -115,15 +128,18 @@ Theme typography is the site-wide base:
|
|
|
115
128
|
typography:
|
|
116
129
|
fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
|
|
117
130
|
preset: quiet-gallery
|
|
131
|
+
rhythm: normal
|
|
118
132
|
```
|
|
119
133
|
|
|
120
|
-
A page-level `presentation.typography.preset` changes the typographic
|
|
121
|
-
that page. A section-level `sections[].presentation.typography.preset`
|
|
122
|
-
the typographic
|
|
134
|
+
A page-level `presentation.typography.preset` changes the typographic character
|
|
135
|
+
for that page. A section-level `sections[].presentation.typography.preset`
|
|
136
|
+
changes the typographic character for that section. `rhythm` is inherited
|
|
137
|
+
separately, so changing preset does not change spacing unless `rhythm` is also
|
|
138
|
+
set.
|
|
123
139
|
|
|
124
|
-
If a section sets `typography.
|
|
125
|
-
a section only sets `typography.overrides`, it keeps the resolved page
|
|
126
|
-
and changes only the specified values.
|
|
140
|
+
If a section sets `typography.rhythm`, that section changes text-near spacing.
|
|
141
|
+
If a section only sets `typography.overrides`, it keeps the resolved page
|
|
142
|
+
preset and rhythm and changes only the specified values.
|
|
127
143
|
|
|
128
144
|
Example section override:
|
|
129
145
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
# navigation:
|
|
8
8
|
# brand: site-wide brand/home text; defaults to the homepage title
|
|
9
9
|
# layout:
|
|
10
|
+
# density: compact | normal | airy
|
|
10
11
|
# pageWidth: CSS length, e.g. 2048px
|
|
11
12
|
# gutter:
|
|
12
13
|
# desktop: CSS length or clamp(), e.g. clamp(1.25rem, 4vw, 3rem)
|
|
@@ -18,9 +19,6 @@
|
|
|
18
19
|
# sectionGap:
|
|
19
20
|
# desktop: CSS length or clamp(), e.g. clamp(1.8rem, 3vw, 2.75rem)
|
|
20
21
|
# mobile: CSS length, e.g. 1.65rem
|
|
21
|
-
# subheadingTop:
|
|
22
|
-
# desktop: CSS length, e.g. 1.35rem
|
|
23
|
-
# mobile: CSS length, e.g. 1.1rem
|
|
24
22
|
# gallery:
|
|
25
23
|
# width: CSS length, e.g. 55vw
|
|
26
24
|
# maxAvailableWidthPercent:
|
|
@@ -32,14 +30,19 @@
|
|
|
32
30
|
# typography:
|
|
33
31
|
# fontFamily: CSS font-family stack
|
|
34
32
|
# preset: quiet-gallery | compact-gallery | text-forward | statement
|
|
33
|
+
# rhythm: compact | normal | airy
|
|
35
34
|
# overrides:
|
|
36
35
|
# headings:
|
|
37
36
|
# h2:
|
|
38
37
|
# size: small | medium | large | xlarge
|
|
39
38
|
# h3:
|
|
40
39
|
# size: small | medium | large | xlarge
|
|
40
|
+
# spacingBefore: CSS length, e.g. 1.2em
|
|
41
|
+
# spacingAfter: CSS length, e.g. 0.45em
|
|
41
42
|
# h4:
|
|
42
43
|
# size: small | medium | large | xlarge
|
|
44
|
+
# spacingBefore: CSS length, e.g. 0.9em
|
|
45
|
+
# spacingAfter: CSS length, e.g. 0.35em
|
|
43
46
|
# presentation:
|
|
44
47
|
# backgroundColor: quoted hex color, e.g. "#000000"
|
|
45
48
|
# textColor: quoted hex color, e.g. "#f7f4ee"
|
|
@@ -53,6 +56,7 @@
|
|
|
53
56
|
# textColor: quoted hex color
|
|
54
57
|
# norna:end theme-help
|
|
55
58
|
layout:
|
|
59
|
+
density: compact
|
|
56
60
|
pageWidth: 2048px
|
|
57
61
|
gutter:
|
|
58
62
|
desktop: clamp(1.25rem, 4vw, 3rem)
|
|
@@ -67,21 +71,12 @@ layout:
|
|
|
67
71
|
finalSectionBottom:
|
|
68
72
|
desktop: clamp(1.8rem, 3vw, 2.75rem)
|
|
69
73
|
mobile: 1.65rem
|
|
70
|
-
sectionHeadingToBody:
|
|
71
|
-
desktop: 0.55rem
|
|
72
|
-
mobile: 0.45rem
|
|
73
74
|
bodyToImages:
|
|
74
75
|
desktop: 1.25rem
|
|
75
76
|
mobile: 1rem
|
|
76
77
|
imageGap:
|
|
77
78
|
desktop: clamp(1.25rem, 2.8vw, 2rem)
|
|
78
79
|
mobile: 1.8rem
|
|
79
|
-
subheadingTop:
|
|
80
|
-
desktop: 1.35rem
|
|
81
|
-
mobile: 1.1rem
|
|
82
|
-
subheadingRuleTop:
|
|
83
|
-
desktop: 0.65rem
|
|
84
|
-
mobile: 0.55rem
|
|
85
80
|
gallery:
|
|
86
81
|
width: 55vw
|
|
87
82
|
maxAvailableWidthPercent:
|
|
@@ -93,14 +88,17 @@ gallery:
|
|
|
93
88
|
typography:
|
|
94
89
|
fontFamily: "Arial, 'Helvetica Neue', Helvetica, sans-serif"
|
|
95
90
|
preset: quiet-gallery
|
|
91
|
+
rhythm: compact
|
|
96
92
|
overrides:
|
|
97
93
|
headings:
|
|
98
94
|
h3:
|
|
99
95
|
size: medium
|
|
100
|
-
|
|
96
|
+
spacingBefore: 1.2em
|
|
97
|
+
spacingAfter: 0.45em
|
|
101
98
|
h4:
|
|
102
99
|
size: small
|
|
103
|
-
|
|
100
|
+
spacingBefore: 0.9em
|
|
101
|
+
spacingAfter: 0.35em
|
|
104
102
|
presentation:
|
|
105
103
|
backgroundColor: "#550000"
|
|
106
104
|
textColor: "#ffffff"
|
package/package.json
CHANGED
package/scripts/check-config.mjs
CHANGED
|
@@ -23,6 +23,7 @@ try {
|
|
|
23
23
|
console.log(`Base path: ${projectConfig.site.basePath}`);
|
|
24
24
|
console.log(`Page width: ${projectConfig.layout.pageWidth}`);
|
|
25
25
|
console.log(`Gutter: desktop ${projectConfig.layout.gutter.desktop}, mobile ${projectConfig.layout.gutter.mobile}`);
|
|
26
|
+
console.log(`Layout density: ${projectConfig.layout.density}`);
|
|
26
27
|
console.log(`Image area width: ${projectConfig.gallery.width}`);
|
|
27
28
|
console.log(`Image max available width: desktop ${projectConfig.gallery.maxAvailableWidthPercent.desktop}%, mobile ${projectConfig.gallery.maxAvailableWidthPercent.mobile}%`);
|
|
28
29
|
console.log(`Image max available height: desktop ${projectConfig.gallery.maxAvailableHeightPercent.desktop}%, mobile ${projectConfig.gallery.maxAvailableHeightPercent.mobile}%`);
|
|
@@ -17,6 +17,16 @@ const assertObject = (value, path, sourceLabel = siteConfigLabel) => {
|
|
|
17
17
|
return value;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
const readEnum = (object, key, path, allowedValues, fallback, sourceLabel = siteConfigLabel) => {
|
|
21
|
+
const value = object[key] ?? fallback;
|
|
22
|
+
|
|
23
|
+
if (!allowedValues.includes(value)) {
|
|
24
|
+
throw new Error(`${path}.${key} must be one of ${allowedValues.join(', ')} in ${sourceLabel}.`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return value;
|
|
28
|
+
};
|
|
29
|
+
|
|
20
30
|
const readString = (object, key, path, sourceLabel = siteConfigLabel) => {
|
|
21
31
|
const value = object[key];
|
|
22
32
|
|
|
@@ -304,6 +314,77 @@ const rawDeploy = assertObject(rawConfig.deploy ?? {}, 'deploy');
|
|
|
304
314
|
const rawDeployWatch = assertObject(rawDeploy.watch ?? {}, 'deploy.watch');
|
|
305
315
|
|
|
306
316
|
const defaultFontFamily = "Arial, 'Helvetica Neue', Helvetica, sans-serif";
|
|
317
|
+
const layoutDensityNames = ['compact', 'normal', 'airy'];
|
|
318
|
+
const layoutDensityProfiles = Object.freeze({
|
|
319
|
+
compact: Object.freeze({
|
|
320
|
+
bodyToImages: Object.freeze({
|
|
321
|
+
desktop: '1rem',
|
|
322
|
+
mobile: '0.9rem',
|
|
323
|
+
}),
|
|
324
|
+
finalSectionBottom: Object.freeze({
|
|
325
|
+
desktop: 'clamp(1.2rem, 2.4vw, 2.25rem)',
|
|
326
|
+
mobile: '1.25rem',
|
|
327
|
+
}),
|
|
328
|
+
firstSectionTop: Object.freeze({
|
|
329
|
+
desktop: 'clamp(1rem, 2vw, 1.75rem)',
|
|
330
|
+
mobile: '1rem',
|
|
331
|
+
}),
|
|
332
|
+
imageGap: Object.freeze({
|
|
333
|
+
desktop: 'clamp(1rem, 2vw, 1.5rem)',
|
|
334
|
+
mobile: '1.25rem',
|
|
335
|
+
}),
|
|
336
|
+
sectionGap: Object.freeze({
|
|
337
|
+
desktop: 'clamp(1.2rem, 2.4vw, 2.25rem)',
|
|
338
|
+
mobile: '1.25rem',
|
|
339
|
+
}),
|
|
340
|
+
}),
|
|
341
|
+
normal: Object.freeze({
|
|
342
|
+
bodyToImages: Object.freeze({
|
|
343
|
+
desktop: '1.25rem',
|
|
344
|
+
mobile: '1rem',
|
|
345
|
+
}),
|
|
346
|
+
finalSectionBottom: Object.freeze({
|
|
347
|
+
desktop: 'clamp(1.4rem, 3vw, 2.75rem)',
|
|
348
|
+
mobile: '1.5rem',
|
|
349
|
+
}),
|
|
350
|
+
firstSectionTop: Object.freeze({
|
|
351
|
+
desktop: 'clamp(1.25rem, 3vw, 2.5rem)',
|
|
352
|
+
mobile: '1.25rem',
|
|
353
|
+
}),
|
|
354
|
+
imageGap: Object.freeze({
|
|
355
|
+
desktop: 'clamp(1.25rem, 2.8vw, 2rem)',
|
|
356
|
+
mobile: '1.5rem',
|
|
357
|
+
}),
|
|
358
|
+
sectionGap: Object.freeze({
|
|
359
|
+
desktop: 'clamp(1.4rem, 3vw, 2.75rem)',
|
|
360
|
+
mobile: '1.5rem',
|
|
361
|
+
}),
|
|
362
|
+
}),
|
|
363
|
+
airy: Object.freeze({
|
|
364
|
+
bodyToImages: Object.freeze({
|
|
365
|
+
desktop: '1.5rem',
|
|
366
|
+
mobile: '1.25rem',
|
|
367
|
+
}),
|
|
368
|
+
finalSectionBottom: Object.freeze({
|
|
369
|
+
desktop: 'clamp(2.25rem, 5vw, 4.5rem)',
|
|
370
|
+
mobile: '2rem',
|
|
371
|
+
}),
|
|
372
|
+
firstSectionTop: Object.freeze({
|
|
373
|
+
desktop: 'clamp(2rem, 5vw, 4rem)',
|
|
374
|
+
mobile: '1.5rem',
|
|
375
|
+
}),
|
|
376
|
+
imageGap: Object.freeze({
|
|
377
|
+
desktop: 'clamp(1.5rem, 3.5vw, 2.75rem)',
|
|
378
|
+
mobile: '2rem',
|
|
379
|
+
}),
|
|
380
|
+
sectionGap: Object.freeze({
|
|
381
|
+
desktop: 'clamp(2.25rem, 5vw, 4.5rem)',
|
|
382
|
+
mobile: '2rem',
|
|
383
|
+
}),
|
|
384
|
+
}),
|
|
385
|
+
});
|
|
386
|
+
const layoutDensity = readEnum(rawLayout, 'density', 'layout', layoutDensityNames, 'normal', siteThemeLabel);
|
|
387
|
+
const layoutSpacingDefaults = layoutDensityProfiles[layoutDensity];
|
|
307
388
|
|
|
308
389
|
export const projectConfig = Object.freeze({
|
|
309
390
|
site: Object.freeze({
|
|
@@ -311,44 +392,18 @@ export const projectConfig = Object.freeze({
|
|
|
311
392
|
url: readUrl(rawSite, 'url', 'site'),
|
|
312
393
|
}),
|
|
313
394
|
layout: Object.freeze({
|
|
395
|
+
density: layoutDensity,
|
|
314
396
|
gutter: readResponsiveCssLength(rawLayout, 'gutter', 'layout', Object.freeze({
|
|
315
397
|
desktop: 'clamp(1.25rem, 4vw, 3rem)',
|
|
316
398
|
mobile: '1rem',
|
|
317
399
|
}), siteThemeLabel),
|
|
318
400
|
pageWidth: readCssLength(rawLayout, 'pageWidth', 'layout', '1180px', siteThemeLabel),
|
|
319
401
|
spacing: Object.freeze({
|
|
320
|
-
bodyToImages: readResponsiveCssLength(rawLayoutSpacing, 'bodyToImages', 'layout.spacing',
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
desktop: 'clamp(2.55rem, 4.2vw, 3.9rem)',
|
|
326
|
-
mobile: '2.25rem',
|
|
327
|
-
}), siteThemeLabel),
|
|
328
|
-
firstSectionTop: readResponsiveCssLength(rawLayoutSpacing, 'firstSectionTop', 'layout.spacing', Object.freeze({
|
|
329
|
-
desktop: 'clamp(1.875rem, 3vw, 2.75rem)',
|
|
330
|
-
mobile: '1.375rem',
|
|
331
|
-
}), siteThemeLabel),
|
|
332
|
-
imageGap: readResponsiveCssLength(rawLayoutSpacing, 'imageGap', 'layout.spacing', Object.freeze({
|
|
333
|
-
desktop: 'clamp(1.5rem, 3.5vw, 2.75rem)',
|
|
334
|
-
mobile: '2.75rem',
|
|
335
|
-
}), siteThemeLabel),
|
|
336
|
-
sectionGap: readResponsiveCssLength(rawLayoutSpacing, 'sectionGap', 'layout.spacing', Object.freeze({
|
|
337
|
-
desktop: 'clamp(2.55rem, 4.2vw, 3.9rem)',
|
|
338
|
-
mobile: '2.25rem',
|
|
339
|
-
}), siteThemeLabel),
|
|
340
|
-
sectionHeadingToBody: readResponsiveCssLength(rawLayoutSpacing, 'sectionHeadingToBody', 'layout.spacing', Object.freeze({
|
|
341
|
-
desktop: 'clamp(0.5625rem, 1.25vw, 0.75rem)',
|
|
342
|
-
mobile: '0.4375rem',
|
|
343
|
-
}), siteThemeLabel),
|
|
344
|
-
subheadingRuleTop: readResponsiveCssLength(rawLayoutSpacing, 'subheadingRuleTop', 'layout.spacing', Object.freeze({
|
|
345
|
-
desktop: '1rem',
|
|
346
|
-
mobile: '0.8rem',
|
|
347
|
-
}), siteThemeLabel),
|
|
348
|
-
subheadingTop: readResponsiveCssLength(rawLayoutSpacing, 'subheadingTop', 'layout.spacing', Object.freeze({
|
|
349
|
-
desktop: '2rem',
|
|
350
|
-
mobile: '1.6rem',
|
|
351
|
-
}), siteThemeLabel),
|
|
402
|
+
bodyToImages: readResponsiveCssLength(rawLayoutSpacing, 'bodyToImages', 'layout.spacing', layoutSpacingDefaults.bodyToImages, siteThemeLabel),
|
|
403
|
+
finalSectionBottom: readResponsiveCssLength(rawLayoutSpacing, 'finalSectionBottom', 'layout.spacing', layoutSpacingDefaults.finalSectionBottom, siteThemeLabel),
|
|
404
|
+
firstSectionTop: readResponsiveCssLength(rawLayoutSpacing, 'firstSectionTop', 'layout.spacing', layoutSpacingDefaults.firstSectionTop, siteThemeLabel),
|
|
405
|
+
imageGap: readResponsiveCssLength(rawLayoutSpacing, 'imageGap', 'layout.spacing', layoutSpacingDefaults.imageGap, siteThemeLabel),
|
|
406
|
+
sectionGap: readResponsiveCssLength(rawLayoutSpacing, 'sectionGap', 'layout.spacing', layoutSpacingDefaults.sectionGap, siteThemeLabel),
|
|
352
407
|
}),
|
|
353
408
|
}),
|
|
354
409
|
gallery: Object.freeze({
|