@janga/norna 0.7.23 → 0.7.24
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 +14 -18
- package/astro.config.mjs +12 -0
- package/bin/norna-cli.mjs +6 -0
- package/package.json +13 -2
- package/schemas/category.schema.json +2 -2
- package/schemas/config.schema.json +45 -15
- package/schemas/content-frontmatter.schema.json +7 -7
- package/schemas/page-theme.schema.json +26 -26
- package/schemas/sitewide-content.schema.json +18 -18
- package/schemas/theme.schema.json +246 -246
- package/scripts/build-site.mjs +1 -0
- package/scripts/check-config.mjs +12 -1
- package/scripts/generate-search-index.mjs +57 -0
- package/scripts/init-site.mjs +1 -0
- package/scripts/lib/code-fence-metadata.mjs +223 -0
- package/scripts/lib/edit-source-link.mjs +49 -0
- package/scripts/lib/editor-language-service.mjs +32 -12
- package/scripts/lib/image-presentation.mjs +4 -0
- package/scripts/lib/navigation-model.mjs +34 -13
- package/scripts/lib/navigation-review.mjs +396 -0
- package/scripts/lib/norna-markdown-blocks.mjs +73 -26
- package/scripts/lib/norna-markdown-render-plugin.mjs +64 -1
- package/scripts/lib/page-aliases.mjs +21 -1
- package/scripts/lib/page-markdown.mjs +32 -1
- package/scripts/lib/page-move-plan.mjs +659 -0
- package/scripts/lib/presentation-palette-metadata.mjs +1 -1
- package/scripts/lib/presentation.mjs +1 -10
- package/scripts/lib/project-config.mjs +111 -5
- package/scripts/lib/public-asset-conventions.mjs +36 -2
- package/scripts/lib/schema-definitions.mjs +22 -5
- package/scripts/lib/schema-editor-metadata.mjs +19 -4
- package/scripts/lib/schema-value-definitions.mjs +1 -1
- package/scripts/lib/semantic-callouts.mjs +128 -0
- package/scripts/lib/site-content.mjs +2 -1
- package/scripts/lib/site-link-graph.mjs +33 -2
- package/scripts/lib/site-navigation-tree.mjs +85 -0
- package/scripts/lib/social-image-assets.mjs +30 -0
- package/scripts/lib/theme-presets.mjs +2 -2
- package/scripts/lib/theme-profiles.mjs +0 -4
- package/scripts/move-site-page.mjs +256 -0
- package/scripts/review-navigation.mjs +32 -0
- package/scripts/sync-content-sections.mjs +67 -4
- package/scripts/sync-site-public.mjs +24 -5
- package/src/components/CodeBlockCopyScript.astro +9 -4
- package/src/components/EditSourceLink.astro +17 -0
- package/src/components/ImageCarousel.astro +5 -6
- package/src/components/NavigationPageTree.astro +66 -55
- package/src/components/NavigationTreeControls.astro +77 -0
- package/src/components/PageAliasRedirect.astro +1 -1
- package/src/components/PageList.astro +33 -0
- package/src/components/PageSequenceNavigation.astro +37 -0
- package/src/components/SearchPage.astro +151 -0
- package/src/components/SiteNavigation.astro +35 -8
- package/src/components/SitePage.astro +79 -26
- package/src/components/SiteSection.astro +11 -3
- package/src/components/SiteTreeNavigation.astro +8 -1
- package/src/components/TreeNavigationScript.astro +207 -26
- package/src/layouts/BaseLayout.astro +57 -2
- package/src/lib/sectionContent.ts +32 -3
- package/src/lib/siteNavigation.ts +31 -52
- package/src/lib/sitePublicAssets.ts +1 -0
- package/src/pages/404.astro +110 -0
- package/src/pages/[...slug].astro +15 -5
- package/src/styles/content.css +242 -18
- package/src/styles/media.css +0 -5
- package/src/styles/navigation.css +31 -0
- package/src/styles/page-layout.css +438 -89
- package/src/styles/responsive.css +77 -8
- package/starters/basic/README.md +6 -19
- package/starters/basic/package.json +1 -0
- package/starters/basic/site/pages/000-home/content.md +13 -50
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { getSiteNodePathname } from './site-page-urls.mjs';
|
|
2
2
|
import { sitemapFilename } from './sitemap.mjs';
|
|
3
3
|
|
|
4
|
-
export const
|
|
4
|
+
export const getGeneratedSiteRoutes = ({ searchEnabled = false } = {}) => Object.freeze([
|
|
5
5
|
Object.freeze({
|
|
6
6
|
kind: 'generated-route',
|
|
7
7
|
label: `Norna generated ${sitemapFilename}`,
|
|
8
8
|
pathname: `/${sitemapFilename}`,
|
|
9
9
|
}),
|
|
10
|
+
...(searchEnabled ? [Object.freeze({
|
|
11
|
+
kind: 'generated-route',
|
|
12
|
+
label: 'Norna generated search page',
|
|
13
|
+
pathname: '/search/',
|
|
14
|
+
})] : []),
|
|
10
15
|
]);
|
|
11
16
|
|
|
17
|
+
export const generatedSiteRoutes = getGeneratedSiteRoutes();
|
|
18
|
+
|
|
12
19
|
const getPagePathname = (page) => page.pathname ?? getSiteNodePathname(page.contentFile ?? page);
|
|
13
20
|
const getPageLabel = (page) => page.contentLabel ?? page.contentFile?.contentLabel ?? page.entry?.id ?? getPagePathname(page);
|
|
14
21
|
const getPageAliases = (page) => page.aliases ?? page.data?.page?.aliases ?? [];
|
|
@@ -99,6 +106,19 @@ export const createPageAliasModel = ({
|
|
|
99
106
|
for (const identity of getPublicFileIdentities(file)) addIdentity(identity);
|
|
100
107
|
}
|
|
101
108
|
for (const route of generatedRoutes) {
|
|
109
|
+
const conflict = identitiesByPathname.get(route.pathname);
|
|
110
|
+
if (conflict) {
|
|
111
|
+
diagnostics.push({
|
|
112
|
+
code: 'generated-route-collision',
|
|
113
|
+
contentFile: conflict.kind === 'page'
|
|
114
|
+
? conflict.source.contentFile ?? conflict.source
|
|
115
|
+
: undefined,
|
|
116
|
+
fix: `Move or rename the conflicting source. ${route.label} owns ${route.pathname} while the feature is enabled.`,
|
|
117
|
+
message: `Generated route "${route.pathname}" from ${route.label} conflicts with ${describeIdentity(conflict)}.`,
|
|
118
|
+
severity: 'error',
|
|
119
|
+
});
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
102
122
|
addIdentity(createIdentity({ ...route, source: route }));
|
|
103
123
|
}
|
|
104
124
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getCodeFenceMetadataDiagnostics } from './code-fence-metadata.mjs';
|
|
1
2
|
import {
|
|
2
3
|
getHeadingIdentifierIssues,
|
|
3
4
|
getMarkdownHeadings,
|
|
@@ -11,7 +12,9 @@ import {
|
|
|
11
12
|
extractMarkdownImageReferences,
|
|
12
13
|
extractNornaMarkdownBlockDiagnostics,
|
|
13
14
|
getNornaBlockImageReferences,
|
|
15
|
+
nornaBlockTypes,
|
|
14
16
|
} from './norna-markdown-blocks.mjs';
|
|
17
|
+
import { getSemanticCalloutDiagnostics } from './semantic-callouts.mjs';
|
|
15
18
|
|
|
16
19
|
const normalizeMarkdownWithOffsets = (source) => {
|
|
17
20
|
const input = String(source);
|
|
@@ -172,7 +175,7 @@ const getRegionContent = (regionMarkdown, blocks, regionOffset) => {
|
|
|
172
175
|
return content.filter((item) => item.kind !== 'markdown' || item.markdown.length > 0);
|
|
173
176
|
};
|
|
174
177
|
|
|
175
|
-
const createRegion = ({ heading, nextHeading, headings, source, label, lineOffset }) => {
|
|
178
|
+
const createRegion = ({ calloutErrors, codeFenceErrors, heading, nextHeading, headings, source, label, lineOffset }) => {
|
|
176
179
|
const endOffset = nextHeading?.index ?? source.length;
|
|
177
180
|
const markdown = source.slice(heading.index, endOffset).trimEnd();
|
|
178
181
|
const regionLineOffset = lineOffset + heading.line - 1;
|
|
@@ -197,6 +200,8 @@ const createRegion = ({ heading, nextHeading, headings, source, label, lineOffse
|
|
|
197
200
|
bodyMarkdown: source.slice(heading.index + heading.source.length, endOffset).trimEnd(),
|
|
198
201
|
blocks: blockResult.blocks,
|
|
199
202
|
blockErrors: blockResult.errors,
|
|
203
|
+
calloutErrors: calloutErrors.filter((error) => error.offset >= heading.index && error.offset < endOffset),
|
|
204
|
+
codeFenceErrors: codeFenceErrors.filter((error) => error.offset >= heading.index && error.offset < endOffset),
|
|
200
205
|
content: getRegionContent(markdown, blockResult.blocks, heading.index),
|
|
201
206
|
endOffset,
|
|
202
207
|
heading,
|
|
@@ -220,12 +225,20 @@ export const parsePageMarkdown = async (markdown, options = {}) => {
|
|
|
220
225
|
const label = options.label ?? 'Markdown';
|
|
221
226
|
const lineOffset = options.lineOffset ?? 0;
|
|
222
227
|
const { headings, tree } = await getMarkdownHeadings(source);
|
|
228
|
+
const calloutErrors = getSemanticCalloutDiagnostics(tree, { label, lineOffset });
|
|
229
|
+
const codeFenceErrors = getCodeFenceMetadataDiagnostics(tree, {
|
|
230
|
+
excludedLanguages: nornaBlockTypes,
|
|
231
|
+
label,
|
|
232
|
+
lineOffset,
|
|
233
|
+
});
|
|
223
234
|
const structuralHeadings = headings.filter((heading) => heading.depth <= 2);
|
|
224
235
|
const prelude = structuralHeadings.length > 0
|
|
225
236
|
? source.slice(0, structuralHeadings[0].index)
|
|
226
237
|
: source;
|
|
227
238
|
const pageHeadings = structuralHeadings.filter((heading) => heading.depth === 1);
|
|
228
239
|
const regions = structuralHeadings.map((heading, index) => createRegion({
|
|
240
|
+
calloutErrors,
|
|
241
|
+
codeFenceErrors,
|
|
229
242
|
heading,
|
|
230
243
|
nextHeading: structuralHeadings[index + 1],
|
|
231
244
|
headings,
|
|
@@ -250,6 +263,22 @@ export const parsePageMarkdown = async (markdown, options = {}) => {
|
|
|
250
263
|
regionId: region.id,
|
|
251
264
|
severity: 'error',
|
|
252
265
|
})));
|
|
266
|
+
const calloutDiagnostics = regions.flatMap((region) => region.calloutErrors.map((error) => ({
|
|
267
|
+
code: error.code,
|
|
268
|
+
fix: error.fix,
|
|
269
|
+
line: error.line,
|
|
270
|
+
message: error.message,
|
|
271
|
+
regionId: region.id,
|
|
272
|
+
severity: 'error',
|
|
273
|
+
})));
|
|
274
|
+
const codeFenceDiagnostics = regions.flatMap((region) => region.codeFenceErrors.map((error) => ({
|
|
275
|
+
code: error.code,
|
|
276
|
+
fix: error.fix,
|
|
277
|
+
line: error.line,
|
|
278
|
+
message: error.message,
|
|
279
|
+
regionId: region.id,
|
|
280
|
+
severity: 'error',
|
|
281
|
+
})));
|
|
253
282
|
const blocks = regions.flatMap((region) => region.blocks);
|
|
254
283
|
const links = [
|
|
255
284
|
...extractMarkdownLinks({ source, tree, lineOffset }),
|
|
@@ -279,6 +308,8 @@ export const parsePageMarkdown = async (markdown, options = {}) => {
|
|
|
279
308
|
...headingDiagnostics,
|
|
280
309
|
...blockDiagnostics,
|
|
281
310
|
...noteDiagnostics,
|
|
311
|
+
...calloutDiagnostics,
|
|
312
|
+
...codeFenceDiagnostics,
|
|
282
313
|
],
|
|
283
314
|
headings,
|
|
284
315
|
headingIssues,
|