@janga/norna 0.7.5 → 0.7.7
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 +5 -5
- package/astro.config.mjs +76 -0
- package/bin/norna-cli.mjs +2 -2
- package/docs/README.md +3 -3
- package/docs/commands.md +6 -6
- package/docs/configuration.md +3 -2
- package/docs/content.md +154 -95
- package/docs/design/site-examples-structure.md +1 -1
- package/docs/engine-development.md +4 -4
- package/docs/getting-started.md +6 -4
- package/docs/images-and-metadata.md +112 -20
- package/docs/routes.md +52 -33
- package/docs/site-structure.md +7 -6
- package/docs/theme.md +8 -7
- package/docs/typography.md +5 -5
- package/examples/dog-gallery/site/content.md +41 -46
- package/examples/dog-gallery/site/routes/{dog-care → 010-dog-care}/route-content.md +1 -4
- package/fixtures/basic/site/content.md +2 -4
- package/fixtures/content-model-v2/.astro/collections/site.schema.json +776 -0
- package/fixtures/content-model-v2/.astro/collections/theme.schema.json +668 -0
- package/fixtures/content-model-v2/.astro/content-assets.mjs +4 -0
- package/fixtures/content-model-v2/.astro/content-modules.mjs +1 -0
- package/fixtures/content-model-v2/.astro/content.d.ts +175 -0
- package/fixtures/content-model-v2/.astro/data-store.json +1 -0
- package/fixtures/content-model-v2/.astro/dev-local.json +8 -0
- package/fixtures/content-model-v2/.astro/dev.json +13 -0
- package/fixtures/content-model-v2/.astro/dev.log +231 -0
- package/fixtures/content-model-v2/.astro/settings.json +5 -0
- package/fixtures/content-model-v2/.astro/types.d.ts +2 -0
- package/fixtures/content-model-v2/dist/_astro/GalleryGrid.astro_astro_type_script_index_0_lang.B0kxDyGz.js +1 -0
- package/fixtures/content-model-v2/dist/_astro/SitePage.BbfZub4g.css +1 -0
- package/fixtures/content-model-v2/dist/guide/index.html +3 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/detail-27930b14-971.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/duplicate-49c98f6c-971.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/intro/hero-6d588a83-971.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/plain/image-3770d763-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/routes/010-guide/images/intro/duplicate-5cf614d2-960.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-one-3770d763-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-three-5bdec65e-768.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1080.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1440.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-1600.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-480.webp +0 -0
- package/fixtures/content-model-v2/dist/images/generated/timed/slide-two-26c08aee-768.webp +0 -0
- package/fixtures/content-model-v2/dist/index.html +8 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/_metadata.json +80 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro-D_GIpJIE.js +434 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro-D_GIpJIE.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_aria-query.js +6390 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_aria-query.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_axobject-query.js +2702 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_axobject-query.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_html-escaper.js +65 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_n_html-escaper.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js +455 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/astro_runtime_client_dev-toolbar_entrypoint__js.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/audit-DM9Hkl5B.js +1534 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/audit-DM9Hkl5B.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/embla-carousel.js +1389 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/embla-carousel.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/highlight-DnZ1ULOL.js +48 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/highlight-DnZ1ULOL.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/icons-RyebKi45.js +42 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/icons-RyebKi45.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/package.json +3 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/rolldown-runtime-BvCyGRYZ.js +4 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/settings-DaU-gNnK.js +190 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/settings-DaU-gNnK.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/toolbar-63PA619H.js +458 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/toolbar-63PA619H.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/ui-library--bkcNSYz.js +1016 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/ui-library--bkcNSYz.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/window-jPkpKVcy.js +32 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/window-jPkpKVcy.js.map +1 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/xray-BXCHpEJP.js +111 -0
- package/fixtures/content-model-v2/node_modules/.vite/deps/xray-BXCHpEJP.js.map +1 -0
- package/fixtures/content-model-v2/site/.norna/generated-images.json +210 -0
- package/fixtures/content-model-v2/site/config.mjs +11 -0
- package/fixtures/content-model-v2/site/content.md +84 -0
- package/fixtures/content-model-v2/site/images/card-section/adopt.svg +9 -0
- package/fixtures/content-model-v2/site/images/card-section/foster.svg +12 -0
- package/fixtures/content-model-v2/site/images/intro/detail.jpg +0 -0
- package/fixtures/content-model-v2/site/images/intro/duplicate.jpg +0 -0
- package/fixtures/content-model-v2/site/images/intro/hero.jpg +0 -0
- package/fixtures/content-model-v2/site/images/plain/image.jpg +0 -0
- package/fixtures/content-model-v2/site/images/timed/slide-one.jpg +0 -0
- package/fixtures/content-model-v2/site/images/timed/slide-three.jpg +0 -0
- package/fixtures/content-model-v2/site/images/timed/slide-two.jpg +0 -0
- package/fixtures/content-model-v2/site/routes/010-guide/images/intro/duplicate.jpg +0 -0
- package/fixtures/content-model-v2/site/routes/010-guide/route-content.md +17 -0
- package/fixtures/content-model-v2/site/theme.md +9 -0
- package/package.json +4 -2
- package/scripts/deploy-site.mjs +12 -5
- package/scripts/dev-local.mjs +6 -0
- package/scripts/generate-images.mjs +132 -56
- package/scripts/lib/image-dimensions.mjs +26 -0
- package/scripts/lib/norna-markdown-blocks.mjs +643 -0
- package/scripts/lib/route-model.mjs +17 -0
- package/scripts/lib/site-content.mjs +45 -37
- package/scripts/show-typography.mjs +18 -10
- package/scripts/sync-content-sections.mjs +280 -423
- package/scripts/test-content-check.mjs +59 -45
- package/scripts/test-content-model-v2.mjs +998 -0
- package/scripts/test-engine-commands.mjs +1 -1
- package/scripts/test-package-check.mjs +38 -11
- package/scripts/test-route-model.mjs +32 -0
- package/scripts/test-temporary-visibility.mjs +3 -6
- package/src/components/CardList.astro +77 -0
- package/src/components/GalleryGrid.astro +22 -12
- package/src/components/SiteNavigation.astro +5 -4
- package/src/components/SitePage.astro +12 -6
- package/src/components/SiteSection.astro +35 -13
- package/src/content.config.ts +8 -23
- package/src/lib/generatedImages.ts +50 -10
- package/src/lib/sectionContent.ts +130 -35
- package/src/lib/sitePages.ts +36 -15
- package/src/pages/[slug].astro +3 -3
- package/src/styles/global.css +187 -0
- package/starters/basic/site/content.md +10 -6
- package/starters/project/README.md +2 -2
- package/starters/project/site/content.md +0 -10
- package/starters/project/site/routes/{guide → 010-guide}/route-content.md +0 -6
|
@@ -10,14 +10,17 @@ import {
|
|
|
10
10
|
siteRoutesLabel,
|
|
11
11
|
siteThemeLabel,
|
|
12
12
|
} from './site-paths.mjs';
|
|
13
|
+
import { parseRouteDirectory } from './route-model.mjs';
|
|
13
14
|
|
|
14
|
-
export const
|
|
15
|
+
export const rasterImageExtensions = new Set(['.jpg', '.jpeg', '.png']);
|
|
16
|
+
export const staticImageExtensions = new Set(['.svg']);
|
|
17
|
+
export const supportedImageExtensions = new Set([...rasterImageExtensions, ...staticImageExtensions]);
|
|
15
18
|
|
|
16
19
|
const h2Regex = /^##\s+.*$/gm;
|
|
17
20
|
const explicitHeadingIdRegex = /\s*\{#([a-z0-9-]+)\}\s*$/;
|
|
18
21
|
const inlineStyleReferenceRegex = /\[[^\]\n]+\]\{\.([a-z][a-z0-9-]*)\}/g;
|
|
19
22
|
const frontmatterDelimiterRegex = /^---\s*$/;
|
|
20
|
-
const knownContentTopLevelFrontmatterKeys = new Set(['title', 'description', '
|
|
23
|
+
const knownContentTopLevelFrontmatterKeys = new Set(['title', 'description', 'navigation', 'presentation', 'frame', 'sections']);
|
|
21
24
|
const knownThemeTopLevelFrontmatterKeys = new Set(['navigation', 'layout', 'gallery', 'typography', 'presentation', 'frame']);
|
|
22
25
|
const knownNestedFrontmatterKeys = new Set([
|
|
23
26
|
'align',
|
|
@@ -55,7 +58,6 @@ const knownNestedFrontmatterKeys = new Set([
|
|
|
55
58
|
'mobile',
|
|
56
59
|
'navigation',
|
|
57
60
|
'overrides',
|
|
58
|
-
'order',
|
|
59
61
|
'paragraphSpacing',
|
|
60
62
|
'pageWidth',
|
|
61
63
|
'preset',
|
|
@@ -85,7 +87,9 @@ export const getContentFiles = async () => {
|
|
|
85
87
|
imagesDir: siteImagesDir,
|
|
86
88
|
imagesLabel: siteImagesLabel,
|
|
87
89
|
isHome: true,
|
|
88
|
-
|
|
90
|
+
routeDirectory: null,
|
|
91
|
+
routeId: null,
|
|
92
|
+
routeOrder: 0,
|
|
89
93
|
}];
|
|
90
94
|
const routeEntries = await readdir(siteRoutesDir, { withFileTypes: true }).catch((error) => {
|
|
91
95
|
if (error?.code === 'ENOENT') {
|
|
@@ -98,19 +102,23 @@ export const getContentFiles = async () => {
|
|
|
98
102
|
for (const entry of routeEntries) {
|
|
99
103
|
if (!entry.isDirectory()) continue;
|
|
100
104
|
|
|
101
|
-
const
|
|
102
|
-
const routeDir = path.join(siteRoutesDir,
|
|
105
|
+
const routeDirectory = entry.name;
|
|
106
|
+
const routeDir = path.join(siteRoutesDir, routeDirectory);
|
|
103
107
|
const routeContentPath = path.join(routeDir, 'route-content.md');
|
|
104
108
|
|
|
105
109
|
if (!(await fileExists(routeContentPath))) continue;
|
|
106
110
|
|
|
111
|
+
const { routeId, routeOrder } = parseRouteDirectory(routeDirectory, `${siteRoutesLabel}/${routeDirectory}`);
|
|
112
|
+
|
|
107
113
|
contentFiles.push({
|
|
108
|
-
contentLabel: `${siteRoutesLabel}/${
|
|
114
|
+
contentLabel: `${siteRoutesLabel}/${routeDirectory}/route-content.md`,
|
|
109
115
|
contentPath: routeContentPath,
|
|
110
116
|
imagesDir: path.join(routeDir, 'images'),
|
|
111
|
-
imagesLabel: `${siteRoutesLabel}/${
|
|
117
|
+
imagesLabel: `${siteRoutesLabel}/${routeDirectory}/images`,
|
|
112
118
|
isHome: false,
|
|
113
|
-
|
|
119
|
+
routeDirectory,
|
|
120
|
+
routeId,
|
|
121
|
+
routeOrder,
|
|
114
122
|
});
|
|
115
123
|
}
|
|
116
124
|
|
|
@@ -242,7 +250,7 @@ export const validateFrontmatterStructure = (frontmatter, addIssue, {
|
|
|
242
250
|
if (knownTopLevelFrontmatterKeys.has(key)) continue;
|
|
243
251
|
|
|
244
252
|
const fix = knownNestedFrontmatterKeys.has(key)
|
|
245
|
-
? `Indent "${key}:" under the
|
|
253
|
+
? `Indent "${key}:" under the object it belongs to, or move image content into Norna Markdown blocks.`
|
|
246
254
|
: `Move "${key}:" under the correct parent key, or remove it if it is not part of the ${fileKind} schema.`;
|
|
247
255
|
|
|
248
256
|
addIssue({
|
|
@@ -271,7 +279,6 @@ export const getFrontmatterSections = (frontmatter) => {
|
|
|
271
279
|
const sections = [];
|
|
272
280
|
const lines = frontmatter.split(/\r?\n/);
|
|
273
281
|
let inSections = false;
|
|
274
|
-
let currentSection = null;
|
|
275
282
|
|
|
276
283
|
for (const [index, line] of lines.entries()) {
|
|
277
284
|
if (/^sections:\s*$/.test(line)) {
|
|
@@ -282,30 +289,9 @@ export const getFrontmatterSections = (frontmatter) => {
|
|
|
282
289
|
if (!inSections) continue;
|
|
283
290
|
if (/^[a-zA-Z0-9_-]+:/.test(line)) break;
|
|
284
291
|
|
|
285
|
-
const sectionMatch = line.match(/^\s{2}
|
|
292
|
+
const sectionMatch = line.match(/^\s{2}([a-z0-9-]+):(?:\s+.*)?\s*$/);
|
|
286
293
|
if (sectionMatch) {
|
|
287
|
-
|
|
288
|
-
sections.push(currentSection);
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const carouselMatch = line.match(/^\s{6}-\s+carousel:\s*$/);
|
|
293
|
-
if (carouselMatch && currentSection) {
|
|
294
|
-
currentSection.carousels.push({ images: [], imageReferences: [], line: index + 1 });
|
|
295
|
-
continue;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
const imageMatch = line.match(/^\s{6,}-\s+image:\s*["']?([^"'\n]+)["']?\s*$/);
|
|
299
|
-
if (imageMatch && currentSection) {
|
|
300
|
-
const image = imageMatch[1].trim();
|
|
301
|
-
const isCarouselImage = /^\s{10}-\s+image:/.test(line);
|
|
302
|
-
const carousel = isCarouselImage ? currentSection.carousels.at(-1) : null;
|
|
303
|
-
currentSection.images.push(image);
|
|
304
|
-
currentSection.imageReferences.push({ image, line: index + 1 });
|
|
305
|
-
if (carousel) {
|
|
306
|
-
carousel.images.push(image);
|
|
307
|
-
carousel.imageReferences.push({ image, line: index + 1 });
|
|
308
|
-
}
|
|
294
|
+
sections.push({ id: sectionMatch[1], line: index + 1 });
|
|
309
295
|
}
|
|
310
296
|
}
|
|
311
297
|
|
|
@@ -361,8 +347,9 @@ export const getBodySections = (body) => {
|
|
|
361
347
|
const text = body.slice(start, end).trimEnd();
|
|
362
348
|
const heading = match[0];
|
|
363
349
|
const id = getHeadingId(heading);
|
|
350
|
+
const line = body.slice(0, start).split(/\r?\n/).length;
|
|
364
351
|
|
|
365
|
-
sections.push({ id, heading, text });
|
|
352
|
+
sections.push({ id, heading, line, text });
|
|
366
353
|
}
|
|
367
354
|
|
|
368
355
|
return { prelude, sections };
|
|
@@ -391,7 +378,7 @@ export const getImageFiles = async (directory) => {
|
|
|
391
378
|
return files;
|
|
392
379
|
};
|
|
393
380
|
|
|
394
|
-
export const getImageIndex = async (contentDir, fail) => {
|
|
381
|
+
export const getImageIndex = async (contentDir, fail, contentLabel = siteImagesLabel) => {
|
|
395
382
|
const imageFiles = await getImageFiles(contentDir);
|
|
396
383
|
const imagesByName = new Map();
|
|
397
384
|
|
|
@@ -400,7 +387,7 @@ export const getImageIndex = async (contentDir, fail) => {
|
|
|
400
387
|
const existingPath = imagesByName.get(imageName);
|
|
401
388
|
|
|
402
389
|
if (existingPath) {
|
|
403
|
-
fail(`Duplicate image filename "${imageName}" found at ${
|
|
390
|
+
fail(`Duplicate image filename "${imageName}" found at ${contentLabel}/${toPosixPath(path.relative(contentDir, existingPath))} and ${contentLabel}/${toPosixPath(path.relative(contentDir, imagePath))}. The filename is ambiguous within this page image root.`);
|
|
404
391
|
continue;
|
|
405
392
|
}
|
|
406
393
|
|
|
@@ -409,3 +396,24 @@ export const getImageIndex = async (contentDir, fail) => {
|
|
|
409
396
|
|
|
410
397
|
return imagesByName;
|
|
411
398
|
};
|
|
399
|
+
|
|
400
|
+
export const getImageCandidatesByName = async (contentDir) => {
|
|
401
|
+
const imageFiles = await getImageFiles(contentDir);
|
|
402
|
+
const imagesByName = new Map();
|
|
403
|
+
|
|
404
|
+
for (const imagePath of imageFiles) {
|
|
405
|
+
const imageName = path.basename(imagePath);
|
|
406
|
+
|
|
407
|
+
if (!imagesByName.has(imageName)) {
|
|
408
|
+
imagesByName.set(imageName, []);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
imagesByName.get(imageName).push(imagePath);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
for (const candidates of imagesByName.values()) {
|
|
415
|
+
candidates.sort((left, right) => left.localeCompare(right, 'sv'));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return imagesByName;
|
|
419
|
+
};
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
typographyRhythms,
|
|
10
10
|
} from './lib/typography.mjs';
|
|
11
11
|
import {
|
|
12
|
+
getBodySections,
|
|
12
13
|
getContentFiles,
|
|
13
14
|
readSiteFile,
|
|
14
15
|
splitSiteFile,
|
|
@@ -268,11 +269,11 @@ const formatAnnotatedTypography = (annotated) => ({
|
|
|
268
269
|
resolved: annotateResolvedValues(annotated.resolved, annotated.sources),
|
|
269
270
|
});
|
|
270
271
|
|
|
271
|
-
const
|
|
272
|
+
const getSectionMetadataBlocks = (lines) => {
|
|
272
273
|
const sectionsMap = findMap(lines, 'sections');
|
|
273
|
-
if (!sectionsMap) return
|
|
274
|
+
if (!sectionsMap) return new Map();
|
|
274
275
|
|
|
275
|
-
const sections =
|
|
276
|
+
const sections = new Map();
|
|
276
277
|
let current = null;
|
|
277
278
|
|
|
278
279
|
for (let index = sectionsMap.index + 1; index < lines.length; index += 1) {
|
|
@@ -282,15 +283,16 @@ const getSectionBlocks = (lines) => {
|
|
|
282
283
|
const indent = countIndent(line);
|
|
283
284
|
if (indent <= sectionsMap.indent) break;
|
|
284
285
|
|
|
285
|
-
const sectionMatch = line.match(/^\s{2}
|
|
286
|
+
const sectionMatch = line.match(/^\s{2}([a-z0-9-]+):(?:\s+.*)?\s*$/);
|
|
286
287
|
if (sectionMatch) {
|
|
287
288
|
if (current) current.end = index;
|
|
288
289
|
current = { id: sectionMatch[1], start: index, end: lines.length };
|
|
289
|
-
sections.
|
|
290
|
+
sections.set(current.id, current);
|
|
290
291
|
}
|
|
291
292
|
}
|
|
292
293
|
|
|
293
|
-
const
|
|
294
|
+
const sectionList = Array.from(sections.values());
|
|
295
|
+
const finalSection = sectionList.at(-1);
|
|
294
296
|
if (finalSection) {
|
|
295
297
|
const afterSections = lines.findIndex((line, index) => (
|
|
296
298
|
index > finalSection.start &&
|
|
@@ -328,7 +330,7 @@ const readThemeTypography = async () => {
|
|
|
328
330
|
};
|
|
329
331
|
|
|
330
332
|
const readPageTypography = async (contentFile, themeTypography) => {
|
|
331
|
-
const { frontmatter, frontmatterBody } = await readSiteFile(contentFile.contentPath, contentFile.contentLabel);
|
|
333
|
+
const { frontmatter, frontmatterBody, body } = await readSiteFile(contentFile.contentPath, contentFile.contentLabel);
|
|
332
334
|
const indentationIssues = [];
|
|
333
335
|
validateFrontmatterIndentation(frontmatter, (issue) => indentationIssues.push(issue));
|
|
334
336
|
validateContentFrontmatterStructure(frontmatter, (issue) => indentationIssues.push(issue));
|
|
@@ -345,8 +347,14 @@ const readPageTypography = async (contentFile, themeTypography) => {
|
|
|
345
347
|
? findMap(lines, 'typography', pagePresentation.index + 1, pagePresentation.nextIndex)?.value
|
|
346
348
|
: null;
|
|
347
349
|
const pageTypography = resolveAnnotatedTypographyOverride(themeTypography, pageTypographyConfig ?? undefined, contentFile.contentLabel);
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
+
const sectionMetadataBlocks = getSectionMetadataBlocks(lines);
|
|
351
|
+
const sections = getBodySections(body).sections
|
|
352
|
+
.filter((section) => section.id)
|
|
353
|
+
.map((section) => {
|
|
354
|
+
const metadata = sectionMetadataBlocks.get(section.id);
|
|
355
|
+
const presentation = metadata
|
|
356
|
+
? findMap(lines, 'presentation', metadata.start + 1, metadata.end)
|
|
357
|
+
: null;
|
|
350
358
|
const typography = presentation
|
|
351
359
|
? findMap(lines, 'typography', presentation.index + 1, presentation.nextIndex)?.value
|
|
352
360
|
: null;
|
|
@@ -359,7 +367,7 @@ const readPageTypography = async (contentFile, themeTypography) => {
|
|
|
359
367
|
|
|
360
368
|
return {
|
|
361
369
|
source: contentFile.contentLabel,
|
|
362
|
-
route: contentFile.isHome ? '/' : `/${contentFile.
|
|
370
|
+
route: contentFile.isHome ? '/' : `/${contentFile.routeId}/`,
|
|
363
371
|
pageTypography,
|
|
364
372
|
sections,
|
|
365
373
|
};
|