@janga/norna 0.7.1 → 0.7.3
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/README.md +32 -18
- package/astro.config.mjs +2 -0
- package/bin/norna-cli.mjs +175 -0
- package/bin/norna.mjs +149 -150
- package/docs/README.md +41 -22
- package/docs/commands.md +25 -12
- package/docs/configuration.md +38 -135
- package/docs/content.md +108 -265
- package/docs/{command-organization.md → design/command-organization.md} +64 -60
- package/docs/{site-examples-structure-note.md → design/site-examples-structure.md} +19 -24
- package/docs/engine-development.md +35 -7
- package/docs/getting-started.md +55 -26
- package/docs/images-and-metadata.md +1 -1
- package/docs/local-development.md +14 -1
- package/docs/publishing.md +24 -1
- package/docs/routes.md +90 -0
- package/docs/site-structure.md +18 -10
- package/docs/theme.md +292 -0
- package/docs/typography.md +144 -0
- package/examples/dog-gallery/.astro/collections/site.schema.json +802 -0
- package/examples/dog-gallery/.astro/collections/theme.schema.json +714 -0
- package/examples/dog-gallery/.astro/content-assets.mjs +4 -0
- package/examples/dog-gallery/.astro/content-modules.mjs +1 -0
- package/examples/dog-gallery/.astro/content.d.ts +175 -0
- package/examples/dog-gallery/.astro/data-store.json +1 -0
- package/examples/dog-gallery/.astro/dev-local.json +8 -0
- package/examples/dog-gallery/.astro/dev.json +13 -0
- package/examples/dog-gallery/.astro/dev.log +49 -0
- package/examples/dog-gallery/.astro/settings.json +5 -0
- package/examples/dog-gallery/.astro/types.d.ts +2 -0
- package/examples/dog-gallery/dist/_astro/GalleryGrid.astro_astro_type_script_index_0_lang.B0kxDyGz.js +1 -0
- package/examples/dog-gallery/dist/_astro/SitePage.BFHZm5UG.css +1 -0
- package/examples/dog-gallery/dist/dog-care/index.html +15 -0
- package/examples/dog-gallery/dist/favicon.svg +7 -0
- 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 +43 -0
- package/examples/dog-gallery/dist/robots.txt +2 -0
- package/examples/dog-gallery/node_modules/.vite/deps/_metadata.json +74 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro-D_GIpJIE.js +434 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro-D_GIpJIE.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_axobject-query.js +2702 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/examples/dog-gallery/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/audit-DM9Hkl5B.js +1534 -0
- package/examples/dog-gallery/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/highlight-DnZ1ULOL.js +48 -0
- package/examples/dog-gallery/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/icons-RyebKi45.js +42 -0
- package/examples/dog-gallery/node_modules/.vite/deps/icons-RyebKi45.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/package.json +3 -0
- package/examples/dog-gallery/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +4 -0
- package/examples/dog-gallery/node_modules/.vite/deps/settings-DaU-gNnK.js +190 -0
- package/examples/dog-gallery/node_modules/.vite/deps/settings-DaU-gNnK.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/toolbar-63PA619H.js +458 -0
- package/examples/dog-gallery/node_modules/.vite/deps/toolbar-63PA619H.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/ui-library--bkcNSYz.js +1016 -0
- package/examples/dog-gallery/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/window-jPkpKVcy.js +32 -0
- package/examples/dog-gallery/node_modules/.vite/deps/window-jPkpKVcy.js.map +1 -0
- package/examples/dog-gallery/node_modules/.vite/deps/xray-BXCHpEJP.js +111 -0
- package/examples/dog-gallery/node_modules/.vite/deps/xray-BXCHpEJP.js.map +1 -0
- package/examples/dog-gallery/site/.norna/generated-images.json +226 -0
- package/examples/dog-gallery/site/config.mjs +67 -0
- package/examples/dog-gallery/site/content.md +168 -0
- package/examples/dog-gallery/site/images/black-dogs/black-puppy-meadow.png +0 -0
- package/examples/dog-gallery/site/images/black-dogs/photo-of-a-black-dog.jpg +0 -0
- package/examples/dog-gallery/site/images/brown-dogs/brown-dog.jpg +0 -0
- package/examples/dog-gallery/site/images/brown-dogs/dog-accompanies-master.jpg +0 -0
- package/examples/dog-gallery/site/images/golden-dogs/golden-retriever.jpg +0 -0
- package/examples/dog-gallery/site/images/golden-dogs/toller-puppy.jpg +0 -0
- package/examples/dog-gallery/site/images/white-dogs/white-cute-dog.jpg +0 -0
- package/examples/dog-gallery/site/images/white-dogs/white-puppy-garden.png +0 -0
- package/examples/dog-gallery/site/public/favicon.svg +7 -0
- package/examples/dog-gallery/site/public/robots.txt +2 -0
- package/examples/dog-gallery/site/routes/dog-care/route-content.md +49 -0
- package/examples/dog-gallery/site/theme.md +114 -0
- package/fixtures/basic/site/config.mjs +3 -22
- package/fixtures/basic/site/content.md +1 -1
- package/fixtures/basic/site/theme.md +7 -3
- package/package.json +10 -9
- package/scripts/check-config.mjs +4 -3
- package/scripts/deploy-site.mjs +3 -3
- package/scripts/dev-local.mjs +64 -15
- package/scripts/init-site.mjs +11 -9
- package/scripts/lib/frontmatter-yaml.mjs +85 -0
- package/scripts/lib/presentation.mjs +10 -11
- package/scripts/lib/project-config.mjs +113 -45
- package/scripts/lib/site-content.mjs +21 -2
- package/scripts/lib/site-paths.mjs +18 -3
- package/scripts/lib/theme-config.mjs +34 -0
- package/scripts/lib/typography.mjs +103 -23
- package/scripts/show-typography.mjs +202 -75
- package/scripts/sync-content-sections.mjs +6 -6
- package/scripts/test-cli-discovery.mjs +124 -0
- package/scripts/test-content-check.mjs +3 -4
- package/scripts/test-engine-commands.mjs +20 -6
- package/scripts/test-navigation.mjs +10 -6
- package/scripts/test-package-check.mjs +40 -11
- package/scripts/test-temporary-visibility.mjs +2 -3
- package/src/components/SiteNavigation.astro +7 -5
- package/src/components/SitePage.astro +5 -3
- package/src/components/SiteSection.astro +63 -29
- package/src/content.config.ts +64 -2
- package/src/layouts/BaseLayout.astro +19 -1
- package/src/lib/basePath.ts +21 -0
- package/src/lib/generatedImages.ts +8 -4
- package/src/lib/sectionContent.ts +6 -1
- package/src/lib/sitePublicAssets.ts +8 -1
- package/src/styles/global.css +59 -55
- package/starters/basic/.github/workflows/deploy.yml +3 -3
- package/starters/basic/README.md +30 -14
- package/starters/basic/package.json +3 -3
- package/starters/basic/site/config.mjs +4 -24
- package/starters/basic/site/content.md +44 -9
- package/starters/basic/site/theme.md +113 -16
- package/starters/project/.github/workflows/deploy.yml +65 -0
- package/starters/project/README.md +72 -0
- package/starters/project/package-lock.json +4296 -0
- package/starters/project/package.json +35 -0
- package/starters/project/site/config.mjs +43 -0
- package/starters/project/site/content.md +88 -0
- package/starters/project/site/public/robots.txt +2 -0
- package/starters/project/site/routes/guide/route-content.md +58 -0
- package/starters/project/site/theme.md +15 -0
|
@@ -7,11 +7,31 @@ export const typographyPresetNames = [
|
|
|
7
7
|
|
|
8
8
|
export const typographyPresets = {
|
|
9
9
|
'quiet-gallery': {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
headings: {
|
|
11
|
+
h1: {
|
|
12
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
13
|
+
size: 'large',
|
|
14
|
+
lineHeight: 1.04,
|
|
15
|
+
spacing: '0.55em',
|
|
16
|
+
},
|
|
17
|
+
h2: {
|
|
18
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
19
|
+
size: 'medium',
|
|
20
|
+
lineHeight: 1.08,
|
|
21
|
+
spacing: '0.65em',
|
|
22
|
+
},
|
|
23
|
+
h3: {
|
|
24
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
25
|
+
size: 'small',
|
|
26
|
+
lineHeight: 1.35,
|
|
27
|
+
spacing: '0.9rem',
|
|
28
|
+
},
|
|
29
|
+
h4: {
|
|
30
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
31
|
+
size: 'medium',
|
|
32
|
+
lineHeight: 1.5,
|
|
33
|
+
spacing: '0.85rem',
|
|
34
|
+
},
|
|
15
35
|
},
|
|
16
36
|
body: {
|
|
17
37
|
align: { desktop: 'left', mobile: 'left' },
|
|
@@ -27,15 +47,35 @@ export const typographyPresets = {
|
|
|
27
47
|
},
|
|
28
48
|
},
|
|
29
49
|
'compact-gallery': {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
50
|
+
headings: {
|
|
51
|
+
h1: {
|
|
52
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
53
|
+
size: 'large',
|
|
54
|
+
lineHeight: 1.04,
|
|
55
|
+
spacing: '0.45em',
|
|
56
|
+
},
|
|
57
|
+
h2: {
|
|
58
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
59
|
+
size: 'medium',
|
|
60
|
+
lineHeight: 1.08,
|
|
61
|
+
spacing: '0.45em',
|
|
62
|
+
},
|
|
63
|
+
h3: {
|
|
64
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
65
|
+
size: 'small',
|
|
66
|
+
lineHeight: 1.3,
|
|
67
|
+
spacing: '0.75rem',
|
|
68
|
+
},
|
|
69
|
+
h4: {
|
|
70
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
71
|
+
size: 'medium',
|
|
72
|
+
lineHeight: 1.42,
|
|
73
|
+
spacing: '0.6rem',
|
|
74
|
+
},
|
|
35
75
|
},
|
|
36
76
|
body: {
|
|
37
77
|
align: { desktop: 'left', mobile: 'left' },
|
|
38
|
-
size: '
|
|
78
|
+
size: 'medium',
|
|
39
79
|
lineHeight: 1.42,
|
|
40
80
|
paragraphSpacing: '0.6em',
|
|
41
81
|
},
|
|
@@ -47,15 +87,35 @@ export const typographyPresets = {
|
|
|
47
87
|
},
|
|
48
88
|
},
|
|
49
89
|
'text-forward': {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
90
|
+
headings: {
|
|
91
|
+
h1: {
|
|
92
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
93
|
+
size: 'large',
|
|
94
|
+
lineHeight: 1.06,
|
|
95
|
+
spacing: '0.65em',
|
|
96
|
+
},
|
|
97
|
+
h2: {
|
|
98
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
99
|
+
size: 'medium',
|
|
100
|
+
lineHeight: 1.12,
|
|
101
|
+
spacing: '0.8em',
|
|
102
|
+
},
|
|
103
|
+
h3: {
|
|
104
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
105
|
+
size: 'small',
|
|
106
|
+
lineHeight: 1.35,
|
|
107
|
+
spacing: '1rem',
|
|
108
|
+
},
|
|
109
|
+
h4: {
|
|
110
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
111
|
+
size: 'medium',
|
|
112
|
+
lineHeight: 1.55,
|
|
113
|
+
spacing: '0.85rem',
|
|
114
|
+
},
|
|
55
115
|
},
|
|
56
116
|
body: {
|
|
57
117
|
align: { desktop: 'left', mobile: 'left' },
|
|
58
|
-
size: '
|
|
118
|
+
size: 'medium',
|
|
59
119
|
lineHeight: 1.62,
|
|
60
120
|
paragraphSpacing: '1em',
|
|
61
121
|
},
|
|
@@ -67,15 +127,35 @@ export const typographyPresets = {
|
|
|
67
127
|
},
|
|
68
128
|
},
|
|
69
129
|
statement: {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
130
|
+
headings: {
|
|
131
|
+
h1: {
|
|
132
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
133
|
+
size: 'xlarge',
|
|
134
|
+
lineHeight: 1.02,
|
|
135
|
+
spacing: '0.45em',
|
|
136
|
+
},
|
|
137
|
+
h2: {
|
|
138
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
139
|
+
size: 'large',
|
|
140
|
+
lineHeight: 1.04,
|
|
141
|
+
spacing: '0.5em',
|
|
142
|
+
},
|
|
143
|
+
h3: {
|
|
144
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
145
|
+
size: 'medium',
|
|
146
|
+
lineHeight: 1.18,
|
|
147
|
+
spacing: '0.85rem',
|
|
148
|
+
},
|
|
149
|
+
h4: {
|
|
150
|
+
align: { desktop: 'left', mobile: 'left' },
|
|
151
|
+
size: 'medium',
|
|
152
|
+
lineHeight: 1.42,
|
|
153
|
+
spacing: '0.75rem',
|
|
154
|
+
},
|
|
75
155
|
},
|
|
76
156
|
body: {
|
|
77
157
|
align: { desktop: 'left', mobile: 'left' },
|
|
78
|
-
size: '
|
|
158
|
+
size: 'medium',
|
|
79
159
|
lineHeight: 1.42,
|
|
80
160
|
paragraphSpacing: '0.75em',
|
|
81
161
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { findMap } from './lib/frontmatter-yaml.mjs';
|
|
2
3
|
import {
|
|
3
4
|
defaultTypography,
|
|
4
5
|
resolveTypographyOverride,
|
|
@@ -7,6 +8,8 @@ import {
|
|
|
7
8
|
typographyPresets,
|
|
8
9
|
} from './lib/typography.mjs';
|
|
9
10
|
import {
|
|
11
|
+
getContentFiles,
|
|
12
|
+
readSiteFile,
|
|
10
13
|
splitSiteFile,
|
|
11
14
|
validateContentFrontmatterStructure,
|
|
12
15
|
validateFrontmatterIndentation,
|
|
@@ -21,68 +24,189 @@ import {
|
|
|
21
24
|
|
|
22
25
|
const mode = process.argv[2] ?? 'show';
|
|
23
26
|
|
|
27
|
+
const typographyValuePaths = [
|
|
28
|
+
['headings', 'h1', 'align', 'desktop'],
|
|
29
|
+
['headings', 'h1', 'align', 'mobile'],
|
|
30
|
+
['headings', 'h1', 'size'],
|
|
31
|
+
['headings', 'h1', 'lineHeight'],
|
|
32
|
+
['headings', 'h1', 'spacing'],
|
|
33
|
+
['headings', 'h2', 'align', 'desktop'],
|
|
34
|
+
['headings', 'h2', 'align', 'mobile'],
|
|
35
|
+
['headings', 'h2', 'size'],
|
|
36
|
+
['headings', 'h2', 'lineHeight'],
|
|
37
|
+
['headings', 'h2', 'spacing'],
|
|
38
|
+
['headings', 'h3', 'align', 'desktop'],
|
|
39
|
+
['headings', 'h3', 'align', 'mobile'],
|
|
40
|
+
['headings', 'h3', 'size'],
|
|
41
|
+
['headings', 'h3', 'lineHeight'],
|
|
42
|
+
['headings', 'h3', 'spacing'],
|
|
43
|
+
['headings', 'h4', 'align', 'desktop'],
|
|
44
|
+
['headings', 'h4', 'align', 'mobile'],
|
|
45
|
+
['headings', 'h4', 'size'],
|
|
46
|
+
['headings', 'h4', 'lineHeight'],
|
|
47
|
+
['headings', 'h4', 'spacing'],
|
|
48
|
+
['body', 'align', 'desktop'],
|
|
49
|
+
['body', 'align', 'mobile'],
|
|
50
|
+
['body', 'size'],
|
|
51
|
+
['body', 'lineHeight'],
|
|
52
|
+
['body', 'paragraphSpacing'],
|
|
53
|
+
['caption', 'align', 'desktop'],
|
|
54
|
+
['caption', 'align', 'mobile'],
|
|
55
|
+
['caption', 'size'],
|
|
56
|
+
['caption', 'lineHeight'],
|
|
57
|
+
['caption', 'spacing'],
|
|
58
|
+
];
|
|
24
59
|
const countIndent = (line) => line.match(/^\s*/)?.[0].length ?? 0;
|
|
25
60
|
|
|
26
|
-
const
|
|
27
|
-
|
|
61
|
+
const isPlainObject = (value) => (
|
|
62
|
+
value !== null &&
|
|
63
|
+
typeof value === 'object' &&
|
|
64
|
+
!Array.isArray(value)
|
|
65
|
+
);
|
|
28
66
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
67
|
+
const hasPath = (value, path) => {
|
|
68
|
+
let current = value;
|
|
69
|
+
|
|
70
|
+
for (const segment of path) {
|
|
71
|
+
if (!isPlainObject(current) || !(segment in current)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
current = current[segment];
|
|
32
76
|
}
|
|
33
77
|
|
|
34
|
-
return
|
|
78
|
+
return true;
|
|
35
79
|
};
|
|
36
80
|
|
|
37
|
-
const
|
|
38
|
-
const value = {};
|
|
39
|
-
let index = startIndex;
|
|
81
|
+
const getPath = (value, path) => path.reduce((current, segment) => current?.[segment], value);
|
|
40
82
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!line.trim() || line.trim().startsWith('#')) {
|
|
44
|
-
index += 1;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
83
|
+
const setPath = (value, path, entry) => {
|
|
84
|
+
let current = value;
|
|
47
85
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
86
|
+
for (const segment of path.slice(0, -1)) {
|
|
87
|
+
current[segment] ??= {};
|
|
88
|
+
current = current[segment];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
current[path.at(-1)] = entry;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const annotateResolvedValues = (resolved, sources) => {
|
|
95
|
+
const annotated = {};
|
|
96
|
+
|
|
97
|
+
for (const path of typographyValuePaths) {
|
|
98
|
+
const source = getPath(sources, path);
|
|
99
|
+
setPath(annotated, path, {
|
|
100
|
+
value: getPath(resolved.values, path),
|
|
101
|
+
source: source.source,
|
|
102
|
+
...(source.inherited ? { inherited: true } : {}),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return annotated;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const presetSources = (presetName) => {
|
|
110
|
+
const sources = {};
|
|
111
|
+
|
|
112
|
+
for (const path of typographyValuePaths) {
|
|
113
|
+
setPath(sources, path, {
|
|
114
|
+
source: `preset:${presetName}`,
|
|
115
|
+
inherited: false,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return sources;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const applyOverrideSources = (sources, typographyConfig, sourceLabel) => {
|
|
123
|
+
const overrides = typographyConfig?.overrides;
|
|
124
|
+
if (!overrides) return sources;
|
|
125
|
+
|
|
126
|
+
for (const path of typographyValuePaths) {
|
|
127
|
+
if (hasPath(overrides, path)) {
|
|
128
|
+
setPath(sources, path, {
|
|
129
|
+
source: `${sourceLabel} override`,
|
|
130
|
+
inherited: false,
|
|
131
|
+
});
|
|
63
132
|
}
|
|
64
133
|
}
|
|
65
134
|
|
|
66
|
-
return
|
|
135
|
+
return sources;
|
|
67
136
|
};
|
|
68
137
|
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
138
|
+
const inheritedSources = (sources) => {
|
|
139
|
+
const inherited = structuredClone(sources);
|
|
140
|
+
|
|
141
|
+
for (const path of typographyValuePaths) {
|
|
142
|
+
setPath(inherited, path, {
|
|
143
|
+
...getPath(sources, path),
|
|
144
|
+
inherited: true,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return inherited;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const resolveAnnotatedTypographyConfig = (typographyConfig, sourceLabel) => {
|
|
152
|
+
const resolved = resolveTypographyConfig(typographyConfig ?? defaultTypography);
|
|
153
|
+
const sources = applyOverrideSources(
|
|
154
|
+
presetSources(resolved.preset),
|
|
155
|
+
typographyConfig,
|
|
156
|
+
sourceLabel,
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
preset: {
|
|
161
|
+
value: resolved.preset,
|
|
162
|
+
source: typographyConfig?.preset ? sourceLabel : 'engine default',
|
|
163
|
+
...(typographyConfig?.preset ? {} : { inherited: true }),
|
|
164
|
+
},
|
|
165
|
+
resolved,
|
|
166
|
+
sources,
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const resolveAnnotatedTypographyOverride = (baseAnnotated, typographyConfig, sourceLabel) => {
|
|
171
|
+
if (typographyConfig?.preset) {
|
|
172
|
+
return resolveAnnotatedTypographyConfig(typographyConfig, sourceLabel);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (typographyConfig?.overrides) {
|
|
176
|
+
const resolved = resolveTypographyOverride(baseAnnotated.resolved, typographyConfig);
|
|
177
|
+
const sources = applyOverrideSources(
|
|
178
|
+
inheritedSources(baseAnnotated.sources),
|
|
179
|
+
typographyConfig,
|
|
180
|
+
sourceLabel,
|
|
181
|
+
);
|
|
75
182
|
|
|
76
183
|
return {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
184
|
+
preset: {
|
|
185
|
+
value: resolved.preset,
|
|
186
|
+
source: baseAnnotated.preset.source,
|
|
187
|
+
inherited: true,
|
|
188
|
+
},
|
|
189
|
+
resolved,
|
|
190
|
+
sources,
|
|
80
191
|
};
|
|
81
192
|
}
|
|
82
193
|
|
|
83
|
-
return
|
|
194
|
+
return {
|
|
195
|
+
preset: {
|
|
196
|
+
value: baseAnnotated.resolved.preset,
|
|
197
|
+
source: baseAnnotated.preset.source,
|
|
198
|
+
inherited: true,
|
|
199
|
+
},
|
|
200
|
+
resolved: baseAnnotated.resolved,
|
|
201
|
+
sources: inheritedSources(baseAnnotated.sources),
|
|
202
|
+
};
|
|
84
203
|
};
|
|
85
204
|
|
|
205
|
+
const formatAnnotatedTypography = (annotated) => ({
|
|
206
|
+
preset: annotated.preset,
|
|
207
|
+
resolved: annotateResolvedValues(annotated.resolved, annotated.sources),
|
|
208
|
+
});
|
|
209
|
+
|
|
86
210
|
const getSectionBlocks = (lines) => {
|
|
87
211
|
const sectionsMap = findMap(lines, 'sections');
|
|
88
212
|
if (!sectionsMap) return [];
|
|
@@ -118,8 +242,7 @@ const getSectionBlocks = (lines) => {
|
|
|
118
242
|
return sections;
|
|
119
243
|
};
|
|
120
244
|
|
|
121
|
-
const
|
|
122
|
-
const { frontmatter, frontmatterBody } = splitSiteFile(await readFile(siteContentPath, 'utf8'));
|
|
245
|
+
const readThemeTypography = async () => {
|
|
123
246
|
const themeFile = await readFile(siteThemePath, 'utf8').catch((error) => {
|
|
124
247
|
if (error?.code === 'ENOENT') {
|
|
125
248
|
return '---\n---\n';
|
|
@@ -129,29 +252,38 @@ const readSiteTypography = async () => {
|
|
|
129
252
|
});
|
|
130
253
|
const { frontmatter: themeFrontmatter, frontmatterBody: themeFrontmatterBody } = splitSiteFile(themeFile, siteThemeLabel);
|
|
131
254
|
const indentationIssues = [];
|
|
132
|
-
validateFrontmatterIndentation(frontmatter, (issue) => indentationIssues.push(issue));
|
|
133
|
-
validateContentFrontmatterStructure(frontmatter, (issue) => indentationIssues.push(issue));
|
|
134
255
|
validateFrontmatterIndentation(themeFrontmatter, (issue) => indentationIssues.push(issue));
|
|
135
256
|
validateThemeFrontmatterStructure(themeFrontmatter, (issue) => indentationIssues.push(issue));
|
|
136
257
|
if (indentationIssues.length > 0) {
|
|
137
258
|
throw new Error([
|
|
138
|
-
`Cannot inspect typography because ${
|
|
259
|
+
`Cannot inspect typography because ${siteThemeLabel} has invalid frontmatter.`,
|
|
139
260
|
...indentationIssues.map((issue) => `- ${issue.message}`),
|
|
140
261
|
].join('\n'));
|
|
141
262
|
}
|
|
142
263
|
|
|
143
|
-
const lines = frontmatterBody.split(/\r?\n/);
|
|
144
264
|
const themeLines = themeFrontmatterBody.split(/\r?\n/);
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
265
|
+
const themeTypographyConfig = findMap(themeLines, 'typography', 0, themeLines.length, 0)?.value;
|
|
266
|
+
return resolveAnnotatedTypographyConfig(themeTypographyConfig ?? defaultTypography, siteThemeLabel);
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const readPageTypography = async (contentFile, themeTypography) => {
|
|
270
|
+
const { frontmatter, frontmatterBody } = await readSiteFile(contentFile.contentPath, contentFile.contentLabel);
|
|
271
|
+
const indentationIssues = [];
|
|
272
|
+
validateFrontmatterIndentation(frontmatter, (issue) => indentationIssues.push(issue));
|
|
273
|
+
validateContentFrontmatterStructure(frontmatter, (issue) => indentationIssues.push(issue));
|
|
274
|
+
if (indentationIssues.length > 0) {
|
|
275
|
+
throw new Error([
|
|
276
|
+
`Cannot inspect typography because ${contentFile.contentLabel} has invalid frontmatter.`,
|
|
277
|
+
...indentationIssues.map((issue) => `- ${issue.message}`),
|
|
278
|
+
].join('\n'));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const lines = frontmatterBody.split(/\r?\n/);
|
|
149
282
|
const pagePresentation = findMap(lines, 'presentation', 0, lines.length, 0);
|
|
150
283
|
const pageTypographyConfig = pagePresentation
|
|
151
284
|
? findMap(lines, 'typography', pagePresentation.index + 1, pagePresentation.nextIndex)?.value
|
|
152
285
|
: null;
|
|
153
|
-
const
|
|
154
|
-
const pageTypography = resolveTypographyOverride(themeTypography, pageTypographyConfig ?? undefined);
|
|
286
|
+
const pageTypography = resolveAnnotatedTypographyOverride(themeTypography, pageTypographyConfig ?? undefined, contentFile.contentLabel);
|
|
155
287
|
const sections = getSectionBlocks(lines).map((section) => {
|
|
156
288
|
const presentation = findMap(lines, 'presentation', section.start + 1, section.end);
|
|
157
289
|
const typography = presentation
|
|
@@ -160,13 +292,13 @@ const readSiteTypography = async () => {
|
|
|
160
292
|
|
|
161
293
|
return {
|
|
162
294
|
id: section.id,
|
|
163
|
-
typography,
|
|
164
|
-
resolved: resolveTypographyOverride(pageTypography, typography ?? undefined),
|
|
295
|
+
typography: resolveAnnotatedTypographyOverride(pageTypography, typography ?? undefined, `${contentFile.contentLabel} sections.${section.id}`),
|
|
165
296
|
};
|
|
166
297
|
});
|
|
167
298
|
|
|
168
299
|
return {
|
|
169
|
-
|
|
300
|
+
source: contentFile.contentLabel,
|
|
301
|
+
route: contentFile.isHome ? '/' : `/${contentFile.routeFolder}/`,
|
|
170
302
|
pageTypography,
|
|
171
303
|
sections,
|
|
172
304
|
};
|
|
@@ -175,36 +307,31 @@ const readSiteTypography = async () => {
|
|
|
175
307
|
if (mode === 'presets') {
|
|
176
308
|
console.log(toYamlLines(typographyPresets).join('\n'));
|
|
177
309
|
} else if (mode === 'show') {
|
|
178
|
-
const
|
|
310
|
+
const themeTypography = await readThemeTypography();
|
|
311
|
+
const pages = await Promise.all((await getContentFiles()).map((contentFile) => readPageTypography(contentFile, themeTypography)));
|
|
179
312
|
const output = {
|
|
180
|
-
source: siteContentLabel,
|
|
181
313
|
theme: {
|
|
182
314
|
source: siteThemeLabel,
|
|
183
315
|
presentation: {
|
|
184
|
-
typography:
|
|
185
|
-
preset: siteTypography.themeTypography.preset,
|
|
186
|
-
resolved: siteTypography.themeTypography.values,
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
page: {
|
|
191
|
-
typography: {
|
|
192
|
-
preset: siteTypography.pageTypography.preset,
|
|
193
|
-
resolved: siteTypography.pageTypography.values,
|
|
316
|
+
typography: formatAnnotatedTypography(themeTypography),
|
|
194
317
|
},
|
|
195
318
|
},
|
|
196
|
-
|
|
197
|
-
|
|
319
|
+
pages: Object.fromEntries(pages.map((page) => [
|
|
320
|
+
page.route,
|
|
198
321
|
{
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
322
|
+
source: page.source,
|
|
323
|
+
typography: formatAnnotatedTypography(page.pageTypography),
|
|
324
|
+
sections: Object.fromEntries(page.sections.map((section) => [
|
|
325
|
+
section.id,
|
|
326
|
+
{
|
|
327
|
+
typography: formatAnnotatedTypography(section.typography),
|
|
328
|
+
},
|
|
329
|
+
])),
|
|
203
330
|
},
|
|
204
331
|
])),
|
|
205
332
|
};
|
|
206
333
|
|
|
207
334
|
console.log(toYamlLines(output).join('\n'));
|
|
208
335
|
} else {
|
|
209
|
-
throw new Error('Usage: norna typography
|
|
336
|
+
throw new Error('Usage: norna typography presets|show');
|
|
210
337
|
}
|
|
@@ -59,7 +59,7 @@ const promptForWrite = async () => {
|
|
|
59
59
|
if (!process.stdin.isTTY) return false;
|
|
60
60
|
|
|
61
61
|
const rl = createInterface({ input, output });
|
|
62
|
-
const answer = await rl.question(`This will rewrite Markdown sections in ${siteContentLabel} and move
|
|
62
|
+
const answer = await rl.question(`This will rewrite Markdown sections in ${siteContentLabel} and move image files if needed. Continue? [y/N] `);
|
|
63
63
|
rl.close();
|
|
64
64
|
|
|
65
65
|
return answer.trim().toLowerCase() === 'y';
|
|
@@ -269,7 +269,7 @@ const validateRouteContentFiles = async () => {
|
|
|
269
269
|
if (referencedImages.has(imageName)) {
|
|
270
270
|
const previousSectionId = referencedImages.get(imageName);
|
|
271
271
|
const message = `Image "${imageName}" is referenced more than once, in "${previousSectionId}" and "${contentFile.contentLabel}:${section.id}".`;
|
|
272
|
-
const fix = 'Each image filename can be referenced by only one
|
|
272
|
+
const fix = 'Each image filename can be referenced by only one image row.';
|
|
273
273
|
|
|
274
274
|
addIssue({ severity: 'error', sectionId: previousSectionId, message, fix });
|
|
275
275
|
addIssue({
|
|
@@ -291,7 +291,7 @@ const validateRouteContentFiles = async () => {
|
|
|
291
291
|
sectionId: `${contentFile.contentLabel}:${section.id}`,
|
|
292
292
|
sectionLabel: `${contentFile.contentLabel} [${section.id}]`,
|
|
293
293
|
message: `Image "${imageName}" does not exist anywhere under ${contentFile.imagesLabel}/.`,
|
|
294
|
-
fix: `Add the source image to ${contentFile.imagesLabel}/${section.id}/ or remove the
|
|
294
|
+
fix: `Add the source image to ${contentFile.imagesLabel}/${section.id}/ or remove the image row.`,
|
|
295
295
|
});
|
|
296
296
|
continue;
|
|
297
297
|
}
|
|
@@ -380,7 +380,7 @@ const getReportLines = (title) => {
|
|
|
380
380
|
leftKey.localeCompare(rightKey, 'sv')
|
|
381
381
|
));
|
|
382
382
|
|
|
383
|
-
lines.push('', 'Section
|
|
383
|
+
lines.push('', 'Section And Image Issues');
|
|
384
384
|
|
|
385
385
|
for (const [, group] of orderedSectionGroups) {
|
|
386
386
|
lines.push('', `[${group.label}]`);
|
|
@@ -506,7 +506,7 @@ for (const section of frontmatterSections) {
|
|
|
506
506
|
const message = previousSectionId === section.id
|
|
507
507
|
? `Image "${imageName}" is referenced more than once in this section.`
|
|
508
508
|
: `Image "${imageName}" is referenced more than once, in sections "${previousSectionId}" and "${section.id}".`;
|
|
509
|
-
const fix = 'Each image filename can be referenced by only one
|
|
509
|
+
const fix = 'Each image filename can be referenced by only one image row.';
|
|
510
510
|
|
|
511
511
|
addSectionIssue(previousSectionId, { severity: 'error', message, fix });
|
|
512
512
|
if (previousSectionId !== section.id) {
|
|
@@ -522,7 +522,7 @@ for (const section of frontmatterSections) {
|
|
|
522
522
|
addSectionIssue(section.id, {
|
|
523
523
|
severity: 'error',
|
|
524
524
|
message: `Image "${imageName}" does not exist anywhere under ${siteImagesLabel}/.`,
|
|
525
|
-
fix: `Add the source image to ${siteImagesLabel}/${section.id}/ or remove the
|
|
525
|
+
fix: `Add the source image to ${siteImagesLabel}/${section.id}/ or remove the image row.`,
|
|
526
526
|
});
|
|
527
527
|
continue;
|
|
528
528
|
}
|