@janga/norna 0.7.27 → 0.7.28
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 +37 -28
- package/astro.config.mjs +19 -1
- package/bin/norna-cli.mjs +5 -3
- package/package.json +9 -5
- package/schemas/card-list.schema.json +1 -1
- package/schemas/config.schema.json +66 -66
- package/schemas/content-frontmatter.schema.json +16 -7
- package/schemas/manifest.json +49 -3
- package/schemas/page-theme.schema.json +1585 -41
- package/schemas/root-theme.schema.json +1767 -0
- package/schemas/sitewide-content.schema.json +18 -18
- package/schemas/theme.schema.json +243 -243
- package/scripts/add-site-node.mjs +13 -161
- package/scripts/build-site.mjs +11 -6
- package/scripts/check-config.mjs +7 -23
- package/scripts/dev-local.mjs +17 -10
- package/scripts/export-theme-preset.mjs +2 -2
- package/scripts/generate-images.mjs +7 -6
- package/scripts/generate-schemas.mjs +9 -6
- package/scripts/lib/category-destinations.mjs +13 -12
- package/scripts/lib/documentation-links.mjs +1 -1
- package/scripts/lib/documentation-routes.json +67 -60
- package/scripts/lib/docusaurus-migration-audit.mjs +9 -6
- package/scripts/lib/editor-file-policy.mjs +18 -0
- package/scripts/lib/editor-language-service.mjs +53 -55
- package/scripts/lib/editor-page-addresses.mjs +55 -0
- package/scripts/lib/editor-page-placement.mjs +172 -0
- package/scripts/lib/editor-site-editing-tree.mjs +146 -0
- package/scripts/lib/editor-site-files.mjs +153 -0
- package/scripts/lib/editor-site-links.mjs +79 -0
- package/scripts/lib/editor-site-tree.mjs +151 -0
- package/scripts/lib/editor-source-files.mjs +87 -0
- package/scripts/lib/editor-theme-help.mjs +43 -0
- package/scripts/lib/locale-registry.mjs +1 -1
- package/scripts/lib/locales/en.mjs +1 -1
- package/scripts/lib/navigation-model.mjs +2 -44
- package/scripts/lib/navigation-review.mjs +14 -50
- package/scripts/lib/norna-markdown-blocks.mjs +1 -1
- package/scripts/lib/page-aliases.mjs +3 -1
- package/scripts/lib/page-model.mjs +17 -20
- package/scripts/lib/page-move-apply.mjs +117 -0
- package/scripts/lib/page-move-plan.mjs +27 -59
- package/scripts/lib/presentation.mjs +3 -3
- package/scripts/lib/project-config.mjs +7 -8
- package/scripts/lib/schema-definitions.mjs +11 -38
- package/scripts/lib/schema-editor-metadata.mjs +12 -59
- package/scripts/lib/schema-value-definitions.mjs +1 -1
- package/scripts/lib/site-content.mjs +7 -24
- package/scripts/lib/site-conventions.mjs +19 -1
- package/scripts/lib/site-navigation-tree.mjs +2 -7
- package/scripts/lib/site-node-create.mjs +169 -0
- package/scripts/lib/site-paths.mjs +22 -10
- package/scripts/lib/site-structure.mjs +72 -82
- package/scripts/lib/site-upgrade.mjs +30 -0
- package/scripts/lib/source-files.mjs +34 -0
- package/scripts/lib/theme-config.mjs +26 -68
- package/scripts/lib/theme-packages.mjs +47 -0
- package/scripts/lib/theme-presets.mjs +20 -53
- package/scripts/lib/typography.mjs +2 -2
- package/scripts/lib/yaml-config.mjs +1 -1
- package/scripts/lib/yaml-source-edit.mjs +94 -0
- package/scripts/move-site-page.mjs +3 -124
- package/scripts/show-typography.mjs +32 -17
- package/scripts/sync-content-sections.mjs +9 -7
- package/scripts/sync-site-public.mjs +1 -1
- package/scripts/upgrade-site.mjs +17 -0
- package/src/components/AreaNavigationMenu.astro +24 -0
- package/src/components/AreaNavigationPanel.astro +55 -0
- package/src/components/AreaNavigationSwitcher.astro +30 -0
- package/src/components/ImageStackEnhancement.astro +0 -7
- package/src/components/NavigationContinuity.astro +26 -0
- package/src/components/NavigationPageTree.astro +13 -4
- package/src/components/NavigationState.astro +11 -0
- package/src/components/NavigationTreeControls.astro +3 -2
- package/src/components/SearchPage.astro +9 -1
- package/src/components/SectionNavigationScript.astro +106 -26
- package/src/components/SiteNavigation.astro +45 -20
- package/src/components/SitePage.astro +37 -61
- package/src/components/SiteTreeNavigation.astro +38 -18
- package/src/components/TopPageMenu.astro +4 -3
- package/src/components/TreeNavigationScript.astro +50 -57
- package/src/content.config.ts +10 -8
- package/src/layouts/BaseLayout.astro +15 -39
- package/src/lib/areaNavigation.ts +42 -0
- package/src/lib/navigationContinuity.ts +212 -0
- package/src/lib/navigationFollowing.ts +28 -18
- package/src/lib/navigationState.mjs +88 -0
- package/src/lib/navigationStateScript.mjs +76 -0
- package/src/lib/navigationVisibility.ts +9 -0
- package/src/lib/pageThemes.ts +5 -42
- package/src/lib/sectionContent.ts +3 -2
- package/src/lib/siteNavigation.ts +6 -0
- package/src/lib/sitePages.ts +9 -6
- package/src/pages/404.astro +1 -1
- package/src/pages/[...slug].astro +5 -15
- package/src/pages/index.astro +1 -3
- package/src/styles/area-navigation.css +399 -0
- package/src/styles/content.css +2 -29
- package/src/styles/navigation-continuity.css +163 -0
- package/src/styles/page-layout.css +57 -68
- package/src/styles/responsive.css +0 -4
- package/starters/basic/README.md +9 -8
- package/starters/basic/site/{pages/000-home → root}/content.md +2 -2
- package/schemas/category.schema.json +0 -20
- package/src/components/PageContentsNavigation.astro +0 -20
- /package/starters/basic/site/{pages/000-home → root}/images/.gitkeep +0 -0
- /package/starters/basic/site/{theme.yaml → root/tree-theme.yaml} +0 -0
- /package/starters/basic/site/{config.yaml → site-config/settings.yaml} +0 -0
- /package/starters/basic/site/{sitewide-content.yaml → site-config/shared-content.yaml} +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createNavigationStateHelpers } from './navigationState.mjs';
|
|
2
|
+
|
|
3
|
+
// Serialized into a parser-time script. Like the helpers, this entry point must
|
|
4
|
+
// only reference its arguments and browser globals, never module-scope values.
|
|
5
|
+
function restoreEarlyNavigationState(createHelpers) {
|
|
6
|
+
// Restore branches as the parser adds them, before they can be painted.
|
|
7
|
+
// pagereveal may precede this tree and is unavailable in some browsers.
|
|
8
|
+
const script = document.currentScript;
|
|
9
|
+
const container = script?.parentElement;
|
|
10
|
+
if (!container?.hasAttribute('data-navigation-root')) return;
|
|
11
|
+
const scope = script.dataset.navigationStateScope;
|
|
12
|
+
const { storageKeys, initialState, arrivalPolicy, readEntryState, pageIsOpen, sectionsAreOpen } = createHelpers();
|
|
13
|
+
const initialized = new WeakSet();
|
|
14
|
+
const restore = (refresh = false) => {
|
|
15
|
+
try {
|
|
16
|
+
// Establish the scroll limit before restoring a position near its end.
|
|
17
|
+
if (scope === 'desktop' && container.parentElement) {
|
|
18
|
+
const flowTop = container.parentElement.getBoundingClientRect().top + window.scrollY;
|
|
19
|
+
const stickyTop = parseFloat(getComputedStyle(container).top) || 0;
|
|
20
|
+
container.style.setProperty('--navigation-scrollport-top', `${Math.ceil(Math.max(flowTop, stickyTop))}px`);
|
|
21
|
+
}
|
|
22
|
+
const { stateKey, sharedStateKey } = storageKeys(scope,
|
|
23
|
+
container.dataset.navigationRoot, container.dataset.navigationStateRoot);
|
|
24
|
+
const state = initialState(sessionStorage.getItem(stateKey), sessionStorage.getItem(sharedStateKey),
|
|
25
|
+
readEntryState(stateKey));
|
|
26
|
+
const policy = arrivalPolicy(state);
|
|
27
|
+
for (const branch of container.querySelectorAll('.navigation-page-disclosure[data-page-path]')) {
|
|
28
|
+
if (!refresh && initialized.has(branch)) continue;
|
|
29
|
+
branch.open = pageIsOpen(state.disclosure, branch.dataset, policy);
|
|
30
|
+
initialized.add(branch);
|
|
31
|
+
}
|
|
32
|
+
for (const branch of container.querySelectorAll('.navigation-page-sections-disclosure[data-page-path]')) {
|
|
33
|
+
if (!refresh && initialized.has(branch)) continue;
|
|
34
|
+
branch.open = sectionsAreOpen(state.disclosure, branch.dataset, policy);
|
|
35
|
+
initialized.add(branch);
|
|
36
|
+
}
|
|
37
|
+
let scrollContainer = container;
|
|
38
|
+
for (let candidate = container; candidate; candidate = candidate.parentElement) {
|
|
39
|
+
if (/auto|scroll/.test(getComputedStyle(candidate).overflowY)) {
|
|
40
|
+
scrollContainer = candidate;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (state.local.scrollTop > 0 || state.fromEntry) scrollContainer.scrollTop = Math.max(0, state.local.scrollTop);
|
|
45
|
+
if (scope === 'desktop' && !state.fromEntry && state.local.scrollTop <= 0) {
|
|
46
|
+
// A direct arrival in a short viewport can put the selected page
|
|
47
|
+
// below the fold. Reveal its title now, before heading following is
|
|
48
|
+
// paused. An already visible title or restored position stays put.
|
|
49
|
+
const node = container.querySelector('[data-navigation-current-page="true"]');
|
|
50
|
+
const link = node?.querySelector(':scope > .navigation-page-link, :scope > .navigation-page-open-link');
|
|
51
|
+
if (link && link.getBoundingClientRect().width > 0) {
|
|
52
|
+
const box = scrollContainer.getBoundingClientRect();
|
|
53
|
+
const controls = container.querySelector('[data-tree-controls]')?.getBoundingClientRect();
|
|
54
|
+
const top = Math.max(box.top, controls?.bottom ?? box.top) + 12;
|
|
55
|
+
const bottom = box.bottom - 16;
|
|
56
|
+
const row = link.getBoundingClientRect();
|
|
57
|
+
if (row.top < top) scrollContainer.scrollTop += row.top - top;
|
|
58
|
+
else if (row.bottom > bottom) scrollContainer.scrollTop += row.bottom - bottom;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
// Ordinary links and native details remain usable without storage.
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
restore();
|
|
66
|
+
const observer = new MutationObserver(() => restore());
|
|
67
|
+
observer.observe(container, { childList: true, subtree: true });
|
|
68
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
69
|
+
restore();
|
|
70
|
+
observer.disconnect();
|
|
71
|
+
}, { once: true });
|
|
72
|
+
// Reapply before a transition snapshot, including a cached history entry.
|
|
73
|
+
window.addEventListener('pagereveal', () => restore(true));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const getNavigationStateScript = () => `(${restoreEarlyNavigationState.toString()})(${createNavigationStateHelpers.toString()});`;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const isNavigationElementDisplayed = (element: HTMLElement) => {
|
|
2
|
+
if (!element.getClientRects().length || getComputedStyle(element).visibility === 'hidden') return false;
|
|
3
|
+
// Closed native details can retain layout rectangles for their hidden links.
|
|
4
|
+
for (let parent = element.parentElement; parent; parent = parent.parentElement) {
|
|
5
|
+
if (parent instanceof HTMLDetailsElement && !parent.open
|
|
6
|
+
&& !parent.querySelector(':scope > summary')?.contains(element)) return false;
|
|
7
|
+
}
|
|
8
|
+
return true;
|
|
9
|
+
};
|
package/src/lib/pageThemes.ts
CHANGED
|
@@ -1,44 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
validatePageThemeYamlStructure,
|
|
5
|
-
} from '../../scripts/lib/site-content.mjs';
|
|
6
|
-
import { pageThemeSchema } from '../../scripts/lib/schema-definitions.mjs';
|
|
7
|
-
import { sitePagesDir, sitePagesLabel } from '../../scripts/lib/site-paths.mjs';
|
|
8
|
-
import { mergePageThemeConfig } from '../../scripts/lib/theme-presets.mjs';
|
|
9
|
-
import { parseYamlConfig } from '../../scripts/lib/yaml-config.mjs';
|
|
10
|
-
import { getPageDirectoryAncestors } from '../../scripts/lib/page-model.mjs';
|
|
1
|
+
import { selectPageTheme } from '../../scripts/lib/theme-packages.mjs';
|
|
2
|
+
import { siteDir } from '../../scripts/lib/site-paths.mjs';
|
|
11
3
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const getPageTheme = async (pageDirectory: string | null): Promise<PageTheme | null> => {
|
|
18
|
-
if (!pageDirectory) return null;
|
|
19
|
-
|
|
20
|
-
const pageAncestors = getPageDirectoryAncestors(pageDirectory);
|
|
21
|
-
let inheritedData: Record<string, unknown> = {};
|
|
22
|
-
const inheritedIds: string[] = [];
|
|
23
|
-
for (const pageAncestor of pageAncestors) {
|
|
24
|
-
const themeSegments = pageAncestor.split('/');
|
|
25
|
-
const themePath = path.join(sitePagesDir, ...themeSegments, 'theme.yaml');
|
|
26
|
-
const source = await readFile(themePath, 'utf8').catch((error) => {
|
|
27
|
-
if (error?.code === 'ENOENT') return null;
|
|
28
|
-
throw error;
|
|
29
|
-
});
|
|
30
|
-
if (!source) continue;
|
|
31
|
-
const themeLabel = `${sitePagesLabel}/${themeSegments.join('/')}/theme.yaml`;
|
|
32
|
-
|
|
33
|
-
const data = parseYamlConfig(source, themeLabel, {
|
|
34
|
-
schema: pageThemeSchema,
|
|
35
|
-
validateStructure: validatePageThemeYamlStructure,
|
|
36
|
-
});
|
|
37
|
-
inheritedData = mergePageThemeConfig(inheritedData, data);
|
|
38
|
-
inheritedIds.push(`pages/${themeSegments.join('/')}/theme`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return inheritedIds.length > 0
|
|
42
|
-
? { id: inheritedIds.join(' + '), data: inheritedData }
|
|
43
|
-
: null;
|
|
4
|
+
export const getPageTheme = async (pageDirectory: string) => {
|
|
5
|
+
const { selected } = await selectPageTheme({ siteRoot: siteDir, pageDirectory });
|
|
6
|
+
return { id: selected.label, data: selected.config };
|
|
44
7
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getPageImageSourceKey } from '../../scripts/lib/site-conventions.mjs';
|
|
1
2
|
import { markdownToHtml } from 'satteri';
|
|
2
3
|
import { groupRenderedTabs } from '../../scripts/lib/content-tabs.mjs';
|
|
3
4
|
import projectConfig from '../../scripts/lib/project-config.mjs';
|
|
@@ -111,7 +112,7 @@ const applyH3HeadingIds = (
|
|
|
111
112
|
return result;
|
|
112
113
|
};
|
|
113
114
|
|
|
114
|
-
const getImageSourceKey = (page: SitePage, image: string) =>
|
|
115
|
+
const getImageSourceKey = (page: SitePage, image: string) => getPageImageSourceKey(page.pageDirectory, image);
|
|
115
116
|
|
|
116
117
|
const renderHeadingTitleHtml = async (headingSource: string) => {
|
|
117
118
|
const headingMarkdown = headingSource
|
|
@@ -178,7 +179,7 @@ const resolveContentBlocks = async (
|
|
|
178
179
|
}
|
|
179
180
|
if (block.type === 'page-list') {
|
|
180
181
|
if (childPages.length === 0) {
|
|
181
|
-
throw new Error(`${page.contentLabel} line ${block.line}: page-list has no listed direct child pages to display.
|
|
182
|
+
throw new Error(`${page.contentLabel} line ${block.line}: page-list has no listed direct child pages to display. Add a listed direct child page or remove the block.`);
|
|
182
183
|
}
|
|
183
184
|
resolvedBlocks.push({
|
|
184
185
|
type: 'page-list',
|
|
@@ -7,6 +7,12 @@ import {
|
|
|
7
7
|
getSequentialPageNavigation as getSequentialPageNavigationShared,
|
|
8
8
|
} from '../../scripts/lib/site-navigation-tree.mjs';
|
|
9
9
|
|
|
10
|
+
export type CategoryDestinationMap = ReadonlyMap<string, { target: SitePage | null }>;
|
|
11
|
+
|
|
12
|
+
export const getNavigationDestination = (node: SiteNode, categoryDestinations?: CategoryDestinationMap): SiteNode => (
|
|
13
|
+
categoryDestinations?.get(node.pathname)?.target ?? node
|
|
14
|
+
);
|
|
15
|
+
|
|
10
16
|
export type SiteNavigationEntry = {
|
|
11
17
|
node: SiteNode;
|
|
12
18
|
headings: HeadingNavigation[];
|
package/src/lib/sitePages.ts
CHANGED
|
@@ -3,10 +3,10 @@ import path from 'node:path';
|
|
|
3
3
|
import { decodePageEntryId, parsePageDirectoryPath } from '../../scripts/lib/page-model.mjs';
|
|
4
4
|
import { parsePageMarkdown } from '../../scripts/lib/page-markdown.mjs';
|
|
5
5
|
import { readSiteFile } from '../../scripts/lib/site-content.mjs';
|
|
6
|
-
import { homePageDirectory } from '../../scripts/lib/site-conventions.mjs';
|
|
6
|
+
import { homePageDirectory, getPageSourceDirectory } from '../../scripts/lib/site-conventions.mjs';
|
|
7
7
|
import { assertCategoryDestinationModel, createCategoryDestinationModel } from '../../scripts/lib/category-destinations.mjs';
|
|
8
8
|
import { getSiteStructure } from '../../scripts/lib/site-structure.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import { siteDir, siteDirLabel } from '../../scripts/lib/site-paths.mjs';
|
|
10
10
|
|
|
11
11
|
type SiteEntry = CollectionEntry<'site'>;
|
|
12
12
|
|
|
@@ -44,6 +44,7 @@ export type SitePage = SiteNodeBase & {
|
|
|
44
44
|
export type SiteCategory = SiteNodeBase & {
|
|
45
45
|
kind: 'category';
|
|
46
46
|
categorySourceLabel: string;
|
|
47
|
+
description?: string;
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
export type SiteNode = SitePage | SiteCategory;
|
|
@@ -75,8 +76,9 @@ const compareNumberPaths = (left: number[], right: number[]) => {
|
|
|
75
76
|
|
|
76
77
|
const readPageMarkdownDocument = async (entry: SiteEntry) => {
|
|
77
78
|
const pageDirectory = getPageDirectory(entry);
|
|
78
|
-
const
|
|
79
|
-
const
|
|
79
|
+
const contentRelativePath = [getPageSourceDirectory(pageDirectory), 'content.md'].filter(Boolean).join('/');
|
|
80
|
+
const contentLabel = `${siteDirLabel}/${contentRelativePath}`;
|
|
81
|
+
const contentPath = path.join(siteDir, contentRelativePath);
|
|
80
82
|
const { body, frontmatter } = await readSiteFile(contentPath, contentLabel);
|
|
81
83
|
const markdownDocument = await parsePageMarkdown(body, {
|
|
82
84
|
label: contentLabel,
|
|
@@ -141,6 +143,7 @@ const createSiteCategory = (category: Awaited<ReturnType<typeof getSiteStructure
|
|
|
141
143
|
pathSegment: category.pagePath,
|
|
142
144
|
pathname: getPagePathname(category.pagePath),
|
|
143
145
|
categorySourceLabel: category.categorySourceLabel,
|
|
146
|
+
description: category.description,
|
|
144
147
|
pageDirectory: category.pageDirectory,
|
|
145
148
|
pageDirectories: category.pageDirectories,
|
|
146
149
|
pageId: category.pageId,
|
|
@@ -161,7 +164,7 @@ const createSitePages = async (entries: SiteEntry[]) => {
|
|
|
161
164
|
|
|
162
165
|
for (const page of pages) {
|
|
163
166
|
if (page.isHome && page.navigation.listed === false) {
|
|
164
|
-
throw new Error(
|
|
167
|
+
throw new Error(`The homepage at ${siteDirLabel}/root/content.md cannot set navigation.listed to false.`);
|
|
165
168
|
}
|
|
166
169
|
const existing = pathnames.get(page.pathname);
|
|
167
170
|
if (existing) {
|
|
@@ -190,7 +193,7 @@ const createSitePages = async (entries: SiteEntry[]) => {
|
|
|
190
193
|
siblingPageOrders.set(pageOrderKey, page);
|
|
191
194
|
}
|
|
192
195
|
if (!pages.some(({ isHome }) => isHome)) {
|
|
193
|
-
throw new Error(`Homepage
|
|
196
|
+
throw new Error(`Homepage content ${siteDirLabel}/root/content.md is missing.`);
|
|
194
197
|
}
|
|
195
198
|
|
|
196
199
|
return pages.sort((left, right) => (
|
package/src/pages/404.astro
CHANGED
|
@@ -20,7 +20,7 @@ const homePage = sitePages.find((page) => page.isHome);
|
|
|
20
20
|
if (!homePage) throw new Error('The required homepage is missing from the site page model.');
|
|
21
21
|
|
|
22
22
|
const [siteTheme] = await getCollection('theme');
|
|
23
|
-
if (!siteTheme) throw new Error('site/theme.yaml is required. Add
|
|
23
|
+
if (!siteTheme) throw new Error('site/root/tree-theme.yaml is required. Add the shared site theme before building the site.');
|
|
24
24
|
const [sitewide] = await getCollection('sitewide');
|
|
25
25
|
const sitewideData = sitewide?.data ?? {};
|
|
26
26
|
const siteThemeData = siteTheme.data;
|
|
@@ -45,28 +45,18 @@ export async function getStaticPaths() {
|
|
|
45
45
|
? [{ params: { slug: 'search' }, props: { searchPage: true } }]
|
|
46
46
|
: [];
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
params: { slug: destination.category.pathSegment },
|
|
50
|
-
props: destination.kind === 'redirect' ? {
|
|
51
|
-
alias: {
|
|
52
|
-
targetPathname: destination.target.pathname,
|
|
53
|
-
targetTitle: destination.target.title,
|
|
54
|
-
categoryTitle: destination.category.title,
|
|
55
|
-
},
|
|
56
|
-
} : { categoryPath: destination.pathname },
|
|
57
|
-
}));
|
|
58
|
-
return [...pagePaths, ...aliasPaths, ...searchPath, ...categoryPaths];
|
|
48
|
+
return [...pagePaths, ...aliasPaths, ...searchPath];
|
|
59
49
|
}
|
|
60
50
|
|
|
61
|
-
const { alias, entry, searchPage
|
|
51
|
+
const { alias, entry, searchPage } = Astro.props;
|
|
62
52
|
|
|
63
|
-
if (!searchPage && !alias &&
|
|
53
|
+
if (!searchPage && !alias && (!entry || isHomePageEntry(entry))) {
|
|
64
54
|
throw new Error('Page entry is missing.');
|
|
65
55
|
}
|
|
66
56
|
|
|
67
57
|
const currentPage = entry ? await getSitePage(entry) : null;
|
|
68
58
|
|
|
69
|
-
if (!searchPage && !alias && !
|
|
59
|
+
if (!searchPage && !alias && !currentPage?.pathSegment) {
|
|
70
60
|
throw new Error(`Page "${entry.id}" needs a page id.`);
|
|
71
61
|
}
|
|
72
62
|
---
|
|
@@ -75,4 +65,4 @@ if (!searchPage && !alias && !categoryPath && !currentPage?.pathSegment) {
|
|
|
75
65
|
? <SearchPage />
|
|
76
66
|
: alias
|
|
77
67
|
? <PageAliasRedirect targetPathname={alias.targetPathname} targetTitle={alias.targetTitle} categoryTitle={alias.categoryTitle} />
|
|
78
|
-
: <SitePage entry={entry}
|
|
68
|
+
: <SitePage entry={entry} />}
|
package/src/pages/index.astro
CHANGED
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
import { getCollection } from 'astro:content';
|
|
3
3
|
import SitePage from '../components/SitePage.astro';
|
|
4
4
|
import { isHomePageEntry } from '../lib/sitePages';
|
|
5
|
-
import {
|
|
5
|
+
import { siteContentLabel } from '../../scripts/lib/site-paths.mjs';
|
|
6
6
|
|
|
7
|
-
const siteDirectory = (process.env.NORNA_SITE_DIR ?? 'site').trim();
|
|
8
|
-
const siteContentLabel = `${siteDirectory || 'site'}/pages/${homePageDirectory}/content.md`;
|
|
9
7
|
const entries = await getCollection('site');
|
|
10
8
|
const site = entries.find(isHomePageEntry);
|
|
11
9
|
|