@janga/norna 0.7.26 → 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 +51 -35
- package/astro.config.mjs +19 -1
- package/bin/norna-cli.mjs +6 -4
- 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 +17 -8
- 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 +33 -2
- package/scripts/lib/documentation-routes.json +229 -0
- 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 +39 -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 +12 -39
- 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/PageAliasRedirect.astro +44 -3
- 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 +15 -16
- 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 +12 -23
- 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 +5 -31
- 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 +10 -9
- 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
package/src/lib/sitePages.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { CollectionEntry } from 'astro:content';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
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,28 +44,15 @@ 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;
|
|
50
51
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
const stripPageIdPrefix = (id: string) => {
|
|
54
|
-
const markerIndex = id.lastIndexOf(pageIdMarker);
|
|
55
|
-
if (markerIndex === -1) return null;
|
|
56
|
-
|
|
57
|
-
const candidate = id.slice(markerIndex + pageIdMarker.length);
|
|
58
|
-
try {
|
|
59
|
-
return parsePageDirectoryPath(decodePageDirectoryPath(candidate)).pageDirectory;
|
|
60
|
-
} catch {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export const isHomePageEntry = (entry: SiteEntry) => stripPageIdPrefix(entry.id) === homePageDirectory;
|
|
52
|
+
export const isHomePageEntry = (entry: SiteEntry) => decodePageEntryId(siteDirLabel, entry.id) === homePageDirectory;
|
|
66
53
|
|
|
67
54
|
export const getPageDirectory = (entry: SiteEntry) => {
|
|
68
|
-
const pageDirectory =
|
|
55
|
+
const pageDirectory = decodePageEntryId(siteDirLabel, entry.id);
|
|
69
56
|
if (!pageDirectory) throw new Error(`Page entry "${entry.id}" has no valid page directory.`);
|
|
70
57
|
return pageDirectory;
|
|
71
58
|
};
|
|
@@ -89,8 +76,9 @@ const compareNumberPaths = (left: number[], right: number[]) => {
|
|
|
89
76
|
|
|
90
77
|
const readPageMarkdownDocument = async (entry: SiteEntry) => {
|
|
91
78
|
const pageDirectory = getPageDirectory(entry);
|
|
92
|
-
const
|
|
93
|
-
const
|
|
79
|
+
const contentRelativePath = [getPageSourceDirectory(pageDirectory), 'content.md'].filter(Boolean).join('/');
|
|
80
|
+
const contentLabel = `${siteDirLabel}/${contentRelativePath}`;
|
|
81
|
+
const contentPath = path.join(siteDir, contentRelativePath);
|
|
94
82
|
const { body, frontmatter } = await readSiteFile(contentPath, contentLabel);
|
|
95
83
|
const markdownDocument = await parsePageMarkdown(body, {
|
|
96
84
|
label: contentLabel,
|
|
@@ -155,6 +143,7 @@ const createSiteCategory = (category: Awaited<ReturnType<typeof getSiteStructure
|
|
|
155
143
|
pathSegment: category.pagePath,
|
|
156
144
|
pathname: getPagePathname(category.pagePath),
|
|
157
145
|
categorySourceLabel: category.categorySourceLabel,
|
|
146
|
+
description: category.description,
|
|
158
147
|
pageDirectory: category.pageDirectory,
|
|
159
148
|
pageDirectories: category.pageDirectories,
|
|
160
149
|
pageId: category.pageId,
|
|
@@ -175,7 +164,7 @@ const createSitePages = async (entries: SiteEntry[]) => {
|
|
|
175
164
|
|
|
176
165
|
for (const page of pages) {
|
|
177
166
|
if (page.isHome && page.navigation.listed === false) {
|
|
178
|
-
throw new Error(
|
|
167
|
+
throw new Error(`The homepage at ${siteDirLabel}/root/content.md cannot set navigation.listed to false.`);
|
|
179
168
|
}
|
|
180
169
|
const existing = pathnames.get(page.pathname);
|
|
181
170
|
if (existing) {
|
|
@@ -204,7 +193,7 @@ const createSitePages = async (entries: SiteEntry[]) => {
|
|
|
204
193
|
siblingPageOrders.set(pageOrderKey, page);
|
|
205
194
|
}
|
|
206
195
|
if (!pages.some(({ isHome }) => isHome)) {
|
|
207
|
-
throw new Error(`Homepage
|
|
196
|
+
throw new Error(`Homepage content ${siteDirLabel}/root/content.md is missing.`);
|
|
208
197
|
}
|
|
209
198
|
|
|
210
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
|
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/* Area menus, integrated H2 navigation and the tree-mode reading frame. */
|
|
2
|
+
.site-reading-location,
|
|
3
|
+
.area-navigation-switcher {
|
|
4
|
+
display: none;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* An elevated dark panel needs a distinct surface and edge: a black shadow
|
|
8
|
+
cannot separate it from the page. Keep its link feedback distinct as well. */
|
|
9
|
+
:root[data-area-navigation][data-appearance='dark'] {
|
|
10
|
+
--area-menu-background: var(--color-surface-soft-background);
|
|
11
|
+
--area-menu-border: color-mix(in srgb, var(--color-primary-text) 40%, var(--color-surface-soft-background));
|
|
12
|
+
--area-menu-hover-background: var(--color-surface-emphasis-background);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@media (prefers-color-scheme: dark) {
|
|
16
|
+
:root[data-area-navigation][data-appearance='system'] {
|
|
17
|
+
--area-menu-background: var(--color-surface-soft-background);
|
|
18
|
+
--area-menu-border: color-mix(in srgb, var(--color-primary-text) 40%, var(--color-surface-soft-background));
|
|
19
|
+
--area-menu-hover-background: var(--color-surface-emphasis-background);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
:root[data-area-navigation] .site-nav-row {
|
|
24
|
+
position: relative;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
:root[data-area-navigation] .site-nav-item:has(.area-navigation-menu) {
|
|
28
|
+
position: static;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:root[data-area-navigation] .site-nav > ul > .site-nav-item > a,
|
|
32
|
+
:root[data-area-navigation] .area-navigation-menu > summary {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
min-height: var(--target-size-minimum);
|
|
36
|
+
padding-block: 0;
|
|
37
|
+
width: auto;
|
|
38
|
+
color: var(--color-secondary-text);
|
|
39
|
+
font-size: 0.78rem;
|
|
40
|
+
font-weight: 500;
|
|
41
|
+
letter-spacing: 0.08em;
|
|
42
|
+
line-height: 1.2;
|
|
43
|
+
text-transform: uppercase;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:root[data-area-navigation] .area-navigation-menu > summary {
|
|
47
|
+
position: relative;
|
|
48
|
+
isolation: isolate;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Paint around the trigger without moving its label or neighboring links. */
|
|
53
|
+
:root[data-area-navigation] .area-navigation-menu > summary::before {
|
|
54
|
+
position: absolute;
|
|
55
|
+
inset: -0.25rem -0.6rem;
|
|
56
|
+
z-index: -1;
|
|
57
|
+
border: 1px solid transparent;
|
|
58
|
+
border-radius: var(--corner-radius-small);
|
|
59
|
+
content: '';
|
|
60
|
+
pointer-events: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:root[data-area-navigation] .area-navigation-menu > summary:is(:hover, :focus-visible),
|
|
64
|
+
:root[data-area-navigation] .area-navigation-menu[open] > summary,
|
|
65
|
+
:root[data-area-navigation] .site-nav-item-current-branch .area-navigation-menu > summary {
|
|
66
|
+
color: var(--site-top-text-color, var(--color-primary-text));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
:root[data-area-navigation] .area-navigation-menu > summary:is(:hover, :focus-visible)::before,
|
|
70
|
+
:root[data-area-navigation] .area-navigation-menu[open] > summary::before {
|
|
71
|
+
border-color: color-mix(in srgb, currentColor 22%, transparent);
|
|
72
|
+
background: color-mix(in srgb, currentColor 8%, transparent);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
:root[data-area-navigation] .area-navigation-panel {
|
|
76
|
+
--area-menu-width: min(calc(var(--area-menu-columns) * 16rem), calc(100vw - 2rem));
|
|
77
|
+
/* Anchor to the entire sticky row, including wrapped global links. This
|
|
78
|
+
also fits without the optional JavaScript panel-position adjustment. */
|
|
79
|
+
inset-inline-end: 0;
|
|
80
|
+
width: var(--area-menu-width);
|
|
81
|
+
max-width: calc(100vw - 2rem);
|
|
82
|
+
border-radius: var(--corner-radius-medium);
|
|
83
|
+
border-color: var(--area-menu-border, var(--color-border));
|
|
84
|
+
background: var(--area-menu-background, var(--site-top-background-color, var(--color-page)));
|
|
85
|
+
padding: 1rem;
|
|
86
|
+
display: grid;
|
|
87
|
+
grid-template-columns: repeat(var(--area-menu-columns), minmax(0, 1fr));
|
|
88
|
+
gap: 1rem;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:root[data-area-navigation] .area-navigation-choices {
|
|
92
|
+
margin: 0;
|
|
93
|
+
padding: 0;
|
|
94
|
+
list-style: none;
|
|
95
|
+
display: grid;
|
|
96
|
+
grid-column: span var(--area-group-columns);
|
|
97
|
+
grid-template-rows: repeat(var(--area-group-rows), auto);
|
|
98
|
+
grid-template-columns: repeat(var(--area-group-columns), minmax(0, 1fr));
|
|
99
|
+
grid-auto-flow: column;
|
|
100
|
+
grid-auto-columns: minmax(0, 1fr);
|
|
101
|
+
gap: 0.75rem 1rem;
|
|
102
|
+
align-content: start;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
:root[data-area-navigation] [data-area-choice-group='branches'] + [data-area-choice-group='pages'] {
|
|
106
|
+
border-inline-start: 1px solid var(--color-border);
|
|
107
|
+
padding-inline-start: 1rem;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
:root[data-area-navigation] [data-area-choice-group='pages'] {
|
|
111
|
+
row-gap: 0.15rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
:root[data-area-navigation] [data-area-choice-group='pages'] .area-navigation-title {
|
|
115
|
+
font-weight: 400;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
:root[data-area-navigation] .area-navigation-choices a {
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-direction: column;
|
|
121
|
+
gap: 0.45rem;
|
|
122
|
+
height: 100%;
|
|
123
|
+
padding: 0.65rem 0.75rem;
|
|
124
|
+
border-radius: var(--corner-radius-small);
|
|
125
|
+
color: var(--color-primary-text);
|
|
126
|
+
font-size: 0.875rem;
|
|
127
|
+
font-weight: 400;
|
|
128
|
+
letter-spacing: 0;
|
|
129
|
+
line-height: 1.4;
|
|
130
|
+
text-decoration: none;
|
|
131
|
+
text-transform: none;
|
|
132
|
+
overflow-wrap: break-word;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
:root[data-area-navigation] .area-navigation-choices a:is(:hover, :focus-visible) {
|
|
136
|
+
background: var(--area-menu-hover-background, var(--color-surface-soft-background));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
:root[data-area-navigation] .area-navigation-title {
|
|
140
|
+
display: flex;
|
|
141
|
+
justify-content: space-between;
|
|
142
|
+
align-items: baseline;
|
|
143
|
+
gap: 0.4rem;
|
|
144
|
+
font-weight: 500;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
:root[data-area-navigation] .area-navigation-title svg {
|
|
148
|
+
flex: 0 0 auto;
|
|
149
|
+
width: 0.85rem;
|
|
150
|
+
height: 0.85rem;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
:root[data-area-navigation] .area-navigation-description {
|
|
154
|
+
color: var(--color-secondary-text);
|
|
155
|
+
font-size: 0.8rem;
|
|
156
|
+
line-height: 1.55;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
:root[data-area-navigation] .area-navigation-other-roots {
|
|
160
|
+
grid-column: 1 / -1;
|
|
161
|
+
display: flex;
|
|
162
|
+
flex-wrap: wrap;
|
|
163
|
+
gap: 0.25rem 0.75rem;
|
|
164
|
+
margin: 0;
|
|
165
|
+
border-block-start: 1px solid var(--color-border);
|
|
166
|
+
padding: 0.75rem 0 0;
|
|
167
|
+
list-style: none;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
:root[data-area-navigation] .area-navigation-other-roots a {
|
|
171
|
+
display: block;
|
|
172
|
+
padding: 0.45rem 0.75rem;
|
|
173
|
+
border-radius: var(--corner-radius-small);
|
|
174
|
+
color: var(--color-secondary-text);
|
|
175
|
+
font-size: 0.8rem;
|
|
176
|
+
font-weight: 400;
|
|
177
|
+
line-height: 1.4;
|
|
178
|
+
text-decoration: none;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
:root[data-area-navigation] .area-navigation-other-roots a:is(:hover, :focus-visible) {
|
|
182
|
+
background: var(--area-menu-hover-background, var(--color-surface-soft-background));
|
|
183
|
+
color: var(--color-primary-text);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
:root[data-area-navigation] .navigation-area-title {
|
|
187
|
+
display: block;
|
|
188
|
+
margin: 0 0 1rem;
|
|
189
|
+
color: var(--color-primary-text);
|
|
190
|
+
font-size: 0.95rem;
|
|
191
|
+
font-weight: 600;
|
|
192
|
+
text-decoration: none;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
:root[data-area-navigation] a.navigation-area-title:is(:hover, :focus-visible) {
|
|
196
|
+
text-decoration: underline;
|
|
197
|
+
text-underline-offset: 0.25em;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* The sticky controls mask 1.25rem above their box. Keep that background
|
|
201
|
+
below the area's linked title, including its underline. */
|
|
202
|
+
:root[data-area-navigation] .navigation-area-title:has(+ .navigation-tree-controls) {
|
|
203
|
+
margin-block-end: 1.5rem;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Scoped pages are now at the tree's first level. Override the ordinary
|
|
207
|
+
first-level emphasis as well as current-page emphasis at every depth. */
|
|
208
|
+
:root[data-navigation-continuity][data-area-navigation]
|
|
209
|
+
.tree-local-navigation .navigation-page-tree
|
|
210
|
+
:is(.navigation-page-link, .navigation-page-open-link, .navigation-page-summary) {
|
|
211
|
+
font-size: 0.84rem;
|
|
212
|
+
font-weight: 400;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@media (min-width: 961px) {
|
|
216
|
+
:root[data-area-reading-frame] {
|
|
217
|
+
--area-reading-rail-width: 16rem;
|
|
218
|
+
--area-reading-header-height: 4rem;
|
|
219
|
+
--site-top-anchor-offset: calc(var(--area-reading-header-height) + 1px + var(--nav-top-safety-inset));
|
|
220
|
+
--area-reading-outer-margin: max(var(--content-gutter), calc((100vw - max(var(--page-width), 86rem)) / 2));
|
|
221
|
+
--area-reading-content-start: calc(var(--area-reading-outer-margin) + var(--area-reading-rail-width) + var(--local-navigation-gap, clamp(1.5rem, 3vw, 3rem)));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
:root[data-area-reading-frame] .site-page-layout-tree > .site-content {
|
|
225
|
+
grid-column: 2;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* One sticky row shares the article/tree columns. The ordinary header
|
|
229
|
+
measurement supplies anchor offsets and the fixed tree's upper edge. */
|
|
230
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .site-top {
|
|
231
|
+
background: var(--color-page);
|
|
232
|
+
color: var(--color-primary-text);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Keep header geometry stable when Focus reading switches to compact controls. */
|
|
236
|
+
:root[data-area-reading-frame] .site-nav-row {
|
|
237
|
+
min-height: var(--area-reading-header-height);
|
|
238
|
+
padding: 0.625rem 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .site-nav-row {
|
|
242
|
+
display: grid;
|
|
243
|
+
grid-template-columns: var(--area-reading-rail-width) minmax(0, 1fr);
|
|
244
|
+
column-gap: var(--local-navigation-gap, clamp(1.5rem, 3vw, 3rem));
|
|
245
|
+
width: min(calc(100% - (var(--content-gutter) * 2)), max(var(--page-width), 86rem));
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .site-nav-leading {
|
|
249
|
+
grid-column: 1;
|
|
250
|
+
grid-row: 1;
|
|
251
|
+
max-width: calc(100% - 6rem);
|
|
252
|
+
padding-inline-start: 0.35rem;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .site-brand {
|
|
256
|
+
min-width: 0;
|
|
257
|
+
max-width: 100%;
|
|
258
|
+
min-height: 2.25rem;
|
|
259
|
+
overflow: hidden;
|
|
260
|
+
color: inherit;
|
|
261
|
+
text-decoration: none;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
:root[data-area-reading-frame] .site-brand-logo {
|
|
265
|
+
max-width: 100%;
|
|
266
|
+
max-height: 2.25rem;
|
|
267
|
+
object-fit: contain;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .site-nav-actions {
|
|
271
|
+
grid-column: 1;
|
|
272
|
+
grid-row: 1;
|
|
273
|
+
justify-self: end;
|
|
274
|
+
gap: 0.35rem;
|
|
275
|
+
padding-inline-end: 0.75rem;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .site-reading-location {
|
|
279
|
+
display: flex;
|
|
280
|
+
grid-column: 2;
|
|
281
|
+
grid-row: 1;
|
|
282
|
+
align-items: center;
|
|
283
|
+
gap: 0.65rem;
|
|
284
|
+
min-width: 0;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
:root[data-area-reading-frame] .site-reading-location .site-breadcrumbs {
|
|
288
|
+
flex: 1 1 auto;
|
|
289
|
+
min-width: 0;
|
|
290
|
+
min-height: 0;
|
|
291
|
+
width: auto;
|
|
292
|
+
margin: 0;
|
|
293
|
+
padding: 0;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
:root[data-area-reading-frame] .site-reading-location .site-breadcrumbs ol {
|
|
297
|
+
flex-wrap: nowrap;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
:root[data-area-reading-frame] .site-reading-location .site-breadcrumbs li > :is(a, span) {
|
|
301
|
+
overflow: hidden;
|
|
302
|
+
text-overflow: ellipsis;
|
|
303
|
+
white-space: nowrap;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
:root[data-area-reading-frame] .site-reading-location-label {
|
|
307
|
+
font-size: 0.78rem;
|
|
308
|
+
font-weight: 650;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* The in-article breadcrumb remains available in the compact layout. */
|
|
312
|
+
:root[data-area-reading-frame] .site-content > .site-breadcrumbs {
|
|
313
|
+
display: none;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
:root[data-area-reading-frame] .site-content-has-breadcrumbs > .site-section:first-of-type {
|
|
317
|
+
padding-top: var(--space-nav-to-first-section);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .display-settings-panel {
|
|
321
|
+
left: 0;
|
|
322
|
+
right: auto;
|
|
323
|
+
max-height: calc(100svh - 4.5rem);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .tree-local-navigation {
|
|
327
|
+
position: fixed;
|
|
328
|
+
top: var(--site-top-anchor-offset);
|
|
329
|
+
left: var(--area-reading-outer-margin);
|
|
330
|
+
bottom: 0;
|
|
331
|
+
width: var(--area-reading-rail-width);
|
|
332
|
+
max-height: calc(100svh - var(--site-top-anchor-offset));
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
:root[data-area-reading-frame] .site-banners {
|
|
336
|
+
width: calc(100% - var(--area-reading-content-start) - var(--area-reading-outer-margin));
|
|
337
|
+
margin-inline: var(--area-reading-content-start) var(--area-reading-outer-margin);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
:root[data-area-reading-frame]:not([data-focus-reading='on']) .area-navigation-switcher {
|
|
341
|
+
position: static;
|
|
342
|
+
display: block;
|
|
343
|
+
flex: 0 0 auto;
|
|
344
|
+
min-width: 0;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
:root[data-area-reading-frame] .area-navigation-switcher > summary {
|
|
348
|
+
width: 2.25rem;
|
|
349
|
+
height: 2.25rem;
|
|
350
|
+
border-radius: var(--corner-radius-small);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
:root[data-area-reading-frame] .area-navigation-switcher > summary:is(:hover, :focus-visible),
|
|
354
|
+
:root[data-area-reading-frame] .area-navigation-switcher[open] > summary {
|
|
355
|
+
background: var(--color-surface-soft-background);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
:root[data-area-reading-frame] .area-navigation-switcher > summary svg {
|
|
359
|
+
flex: 0 0 auto;
|
|
360
|
+
transform: none;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
:root[data-area-reading-frame] .area-navigation-switcher .area-navigation-panel {
|
|
364
|
+
/* Fit beneath the shared row before the disclosure's toggle event.
|
|
365
|
+
This also keeps the panel visible without JavaScript. */
|
|
366
|
+
inset-inline-start: min(
|
|
367
|
+
calc(var(--area-reading-rail-width) + var(--local-navigation-gap, clamp(1.5rem, 3vw, 3rem))),
|
|
368
|
+
calc(100% - var(--area-menu-width))
|
|
369
|
+
);
|
|
370
|
+
inset-inline-end: auto;
|
|
371
|
+
inset-block-start: 100%;
|
|
372
|
+
max-height: calc(100svh - var(--site-top-anchor-offset) - 1rem);
|
|
373
|
+
background: var(--area-menu-background, var(--color-page));
|
|
374
|
+
color: var(--color-primary-text);
|
|
375
|
+
overscroll-behavior: contain;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
:root[data-area-navigation] .site-page-layout-tree {
|
|
379
|
+
--tree-navigation-width: 16rem;
|
|
380
|
+
grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/* The recovered right column belongs to the content canvas. Do not count
|
|
384
|
+
the old outline allowance a second time for notes or wide blocks. */
|
|
385
|
+
:root[data-area-navigation] .site-page-layout-tree .section-markdown > :is(.norna-table-frame, .code-block) {
|
|
386
|
+
--wide-block-end-width: 100cqi;
|
|
387
|
+
--wide-block-canvas-width: var(--wide-block-end-width);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
:root[data-area-navigation][data-reader-preferences-ready='true'][data-focus-reading='on'] .site-page-layout-tree {
|
|
391
|
+
grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
:root[data-area-navigation][data-reader-preferences-ready='true'][data-focus-reading='on']
|
|
395
|
+
.site-page-layout-tree .section-markdown > :is(.norna-table-frame, .code-block) {
|
|
396
|
+
--wide-block-end-width: 100cqi;
|
|
397
|
+
--wide-block-canvas-width: calc(100cqi + var(--tree-navigation-width) + var(--tree-layout-gap));
|
|
398
|
+
}
|
|
399
|
+
}
|
package/src/styles/content.css
CHANGED
|
@@ -466,7 +466,8 @@ ul {
|
|
|
466
466
|
}
|
|
467
467
|
|
|
468
468
|
.section-markdown > .norna-table-frame {
|
|
469
|
-
|
|
469
|
+
/* Start in the same lane that the layout enhancement tries first. */
|
|
470
|
+
width: var(--wide-block-prose-width);
|
|
470
471
|
}
|
|
471
472
|
|
|
472
473
|
.section-markdown > :is([data-table-layout='prose'], [data-code-layout='prose']) {
|
|
@@ -784,32 +785,10 @@ ul {
|
|
|
784
785
|
}
|
|
785
786
|
}
|
|
786
787
|
|
|
787
|
-
@media (min-width: 1101px) {
|
|
788
|
-
:root[data-reader-preferences-ready='true'][data-focus-reading='on']
|
|
789
|
-
.site-page-layout-tree .section-markdown > :is(.norna-table-frame, .code-block) {
|
|
790
|
-
--wide-block-end-width: calc(100cqi + var(--contents-navigation-width) + var(--tree-layout-gap));
|
|
791
|
-
--wide-block-canvas-width: calc(
|
|
792
|
-
100cqi
|
|
793
|
-
+ var(--tree-navigation-width)
|
|
794
|
-
+ var(--contents-navigation-width)
|
|
795
|
-
+ (var(--tree-layout-gap) * 2)
|
|
796
|
-
);
|
|
797
|
-
--wide-block-canvas-inline-offset: calc(0px - var(--tree-navigation-width) - var(--tree-layout-gap));
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
@media (min-width: 1281px) {
|
|
802
|
-
.site-page-layout-tree:not(.site-page-layout-contents) .section-markdown > :is(.norna-table-frame, .code-block) {
|
|
803
|
-
--wide-block-end-width: calc(100cqi + var(--contents-navigation-width) + var(--tree-layout-gap));
|
|
804
|
-
--wide-block-canvas-width: var(--wide-block-end-width);
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
|
|
808
788
|
:root[data-reader-preferences-ready='true'][data-focus-reading='on'] :is(
|
|
809
789
|
.site-nav,
|
|
810
790
|
.page-nav,
|
|
811
791
|
.tree-local-navigation,
|
|
812
|
-
.page-contents-navigation,
|
|
813
792
|
.site-breadcrumbs,
|
|
814
793
|
.site-footer
|
|
815
794
|
) {
|
|
@@ -835,12 +814,6 @@ ul {
|
|
|
835
814
|
}
|
|
836
815
|
}
|
|
837
816
|
|
|
838
|
-
@media (min-width: 1101px) {
|
|
839
|
-
:root[data-reader-preferences-ready='true'][data-focus-reading='on'] .site-page-layout-tree {
|
|
840
|
-
grid-template-columns: var(--tree-navigation-width) minmax(0, 1fr) var(--contents-navigation-width);
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
|
|
844
817
|
:root[data-reader-preferences-ready='true'][data-focus-reading='on']
|
|
845
818
|
.site-content-has-breadcrumbs > .site-section:first-of-type {
|
|
846
819
|
padding-top: var(--space-nav-to-first-section);
|
|
@@ -983,8 +956,9 @@ ul {
|
|
|
983
956
|
padding: 0.78rem 0.9rem;
|
|
984
957
|
background: var(--color-code-background) !important;
|
|
985
958
|
color: var(--color-code-text);
|
|
986
|
-
font-
|
|
987
|
-
|
|
959
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
960
|
+
font-size: 0.875rem;
|
|
961
|
+
line-height: 1.43;
|
|
988
962
|
text-align: left;
|
|
989
963
|
}
|
|
990
964
|
|