@takazudo/zudo-doc 4.2.1 → 4.4.0
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/CHANGELOG.md +43 -0
- package/README.md +3 -3
- package/bin/zudo-doc.mjs +54 -13
- package/dist/auto-logo/index.d.ts +18 -0
- package/dist/auto-logo/index.js +33 -0
- package/dist/auto-logo/shapes.d.ts +32 -0
- package/dist/auto-logo/shapes.js +183 -0
- package/dist/auto-logo/standalone.d.ts +7 -0
- package/dist/auto-logo/standalone.js +35 -0
- package/dist/color-scheme-utils.d.ts +4 -3
- package/dist/color-scheme-utils.js +1 -1
- package/dist/config/component-tokens.js +2 -2
- package/dist/config.d.ts +23 -1
- package/dist/config.js +3 -0
- package/dist/content.css +4 -3
- package/dist/doc-content-header/index.js +1 -1
- package/dist/doc-history/index.js +1 -1
- package/dist/doc-history-area/index.d.ts +1 -0
- package/dist/doc-history-area/index.js +3 -0
- package/dist/doc-page-shell/index.js +1 -1
- package/dist/doc-pager/index.js +2 -2
- package/dist/eject-logo/config-parse.d.ts +25 -0
- package/dist/eject-logo/config-parse.js +68 -0
- package/dist/eject-logo/config-rewriter.d.ts +22 -0
- package/dist/eject-logo/config-rewriter.js +68 -0
- package/dist/eject-logo/eject.d.ts +18 -0
- package/dist/eject-logo/eject.js +66 -0
- package/dist/eject-logo/index.d.ts +4 -0
- package/dist/eject-logo/index.js +16 -0
- package/dist/eject-logo/site-name.d.ts +21 -0
- package/dist/eject-logo/site-name.js +31 -0
- package/dist/features.css +8 -29
- package/dist/header/header.js +14 -6
- package/dist/header/nav-class-tokens.d.ts +12 -0
- package/dist/header/nav-class-tokens.js +80 -0
- package/dist/header/nav-overflow-script.js +33 -16
- package/dist/home-page/index.d.ts +34 -5
- package/dist/home-page/index.js +95 -38
- package/dist/home-page/prepare-home-data.d.ts +9 -0
- package/dist/home-page/prepare-home-data.js +10 -3
- package/dist/html-preview-wrapper/highlight-runtime.d.ts +40 -0
- package/dist/html-preview-wrapper/highlight-runtime.js +58 -0
- package/dist/html-preview-wrapper/highlighted-code.d.ts +3 -2
- package/dist/html-preview-wrapper/highlighted-code.js +11 -30
- package/dist/i18n-defaults/index.js +3 -0
- package/dist/metainfo/doc-metainfo.js +35 -22
- package/dist/plugins/doc-history.js +6 -2
- package/dist/plugins/internal/doc-history/index.d.ts +2 -0
- package/dist/plugins/internal/doc-history/index.js +5 -0
- package/dist/plugins/internal/doc-history/pre-build.d.ts +2 -0
- package/dist/plugins/internal/doc-history/pre-build.js +3 -0
- package/dist/preset.d.ts +1 -0
- package/dist/preset.js +2 -1
- package/dist/routes/index.js +13 -3
- package/dist/routes/locale-index.js +12 -2
- package/dist/safelist.css +1 -1
- package/dist/settings.d.ts +15 -0
- package/dist/sidebar-tree-island/index.js +3 -3
- package/dist/theme-cli/config-scanner.js +47 -0
- package/dist/theme-packs/academia/fonts/CourierPrime-400-latin.woff2 +0 -0
- package/dist/theme-packs/academia/fonts/CourierPrime-700-latin.woff2 +0 -0
- package/dist/theme-packs/academia/fonts/OFL.txt +94 -0
- package/dist/theme-packs/academia/fonts/SourceSerif4-italic-latin.woff2 +0 -0
- package/dist/theme-packs/academia/fonts/SourceSerif4-latin.woff2 +0 -0
- package/dist/theme-packs/academia/meta.json +37 -0
- package/dist/theme-packs/academia/pack.css +505 -0
- package/dist/theme-packs/bauhaus/fonts/ArchivoBlack-latin.woff2 +0 -0
- package/dist/theme-packs/bauhaus/fonts/Jost-latin.woff2 +0 -0
- package/dist/theme-packs/bauhaus/fonts/OFL.txt +95 -0
- package/dist/theme-packs/bauhaus/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/bauhaus/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/bauhaus/meta.json +38 -0
- package/dist/theme-packs/bauhaus/pack.css +614 -0
- package/dist/theme-packs/blueprint/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/blueprint/fonts/IBMPlexMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/blueprint/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
- package/dist/theme-packs/blueprint/fonts/IBMPlexMono-500-latin.woff2 +0 -0
- package/dist/theme-packs/blueprint/fonts/Inter-latin-ext.woff2 +0 -0
- package/dist/theme-packs/blueprint/fonts/Inter-latin.woff2 +0 -0
- package/dist/theme-packs/blueprint/fonts/JosefinSans-latin.woff2 +0 -0
- package/dist/theme-packs/blueprint/fonts/OFL.txt +95 -0
- package/dist/theme-packs/blueprint/meta.json +38 -0
- package/dist/theme-packs/blueprint/pack.css +577 -0
- package/dist/theme-packs/botanica/fonts/CormorantGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/botanica/fonts/CourierPrime-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/botanica/fonts/CourierPrime-400-latin.woff2 +0 -0
- package/dist/theme-packs/botanica/fonts/CourierPrime-700-latin-ext.woff2 +0 -0
- package/dist/theme-packs/botanica/fonts/CourierPrime-700-latin.woff2 +0 -0
- package/dist/theme-packs/botanica/fonts/CrimsonPro-latin-italic.woff2 +0 -0
- package/dist/theme-packs/botanica/fonts/CrimsonPro-latin.woff2 +0 -0
- package/dist/theme-packs/botanica/fonts/OFL.txt +95 -0
- package/dist/theme-packs/botanica/meta.json +38 -0
- package/dist/theme-packs/botanica/pack.css +546 -0
- package/dist/theme-packs/brutalist/meta.json +1 -1
- package/dist/theme-packs/brutalist/pack.css +10 -9
- package/dist/theme-packs/eink/fonts/CourierPrime-400-latin-ext.woff2 +0 -0
- package/dist/theme-packs/eink/fonts/CourierPrime-400-latin.woff2 +0 -0
- package/dist/theme-packs/eink/fonts/CourierPrime-700-latin-ext.woff2 +0 -0
- package/dist/theme-packs/eink/fonts/CourierPrime-700-latin.woff2 +0 -0
- package/dist/theme-packs/eink/fonts/EBGaramond-latin-italic.woff2 +0 -0
- package/dist/theme-packs/eink/fonts/EBGaramond-latin.woff2 +0 -0
- package/dist/theme-packs/eink/fonts/OFL.txt +94 -0
- package/dist/theme-packs/eink/meta.json +37 -0
- package/dist/theme-packs/eink/pack.css +490 -0
- package/dist/theme-packs/foundry/meta.json +1 -1
- package/dist/theme-packs/foundry/pack.css +2 -2
- package/dist/theme-packs/hearth/meta.json +1 -1
- package/dist/theme-packs/hearth/pack.css +15 -4
- package/dist/theme-packs/nocturne/pack.css +4 -0
- package/dist/theme-packs/observatory/meta.json +1 -1
- package/dist/theme-packs/observatory/pack.css +4 -1
- package/dist/theme-packs/onyx/pack.css +6 -0
- package/dist/theme-packs/phosphor/pack.css +4 -0
- package/dist/theme-packs/riso/fonts/ArchivoBlack-latin.woff2 +0 -0
- package/dist/theme-packs/riso/fonts/OFL.txt +95 -0
- package/dist/theme-packs/riso/fonts/SpaceGrotesk-latin.woff2 +0 -0
- package/dist/theme-packs/riso/fonts/SpaceMono-400-italic-latin.woff2 +0 -0
- package/dist/theme-packs/riso/fonts/SpaceMono-400-latin.woff2 +0 -0
- package/dist/theme-packs/riso/fonts/SpaceMono-700-latin.woff2 +0 -0
- package/dist/theme-packs/riso/meta.json +38 -0
- package/dist/theme-packs/riso/pack.css +602 -0
- package/dist/theme-packs/sakura/fonts/MPlus1Code-400-latin.woff2 +0 -0
- package/dist/theme-packs/sakura/fonts/MPlus1Code-500-latin.woff2 +0 -0
- package/dist/theme-packs/sakura/fonts/Nunito-latin.woff2 +0 -0
- package/dist/theme-packs/sakura/fonts/OFL.txt +95 -0
- package/dist/theme-packs/sakura/fonts/ShipporiMincho-600-latin.woff2 +0 -0
- package/dist/theme-packs/sakura/fonts/ShipporiMincho-700-latin.woff2 +0 -0
- package/dist/theme-packs/sakura/meta.json +38 -0
- package/dist/theme-packs/sakura/pack.css +473 -0
- package/dist/theme-packs/scandi/fonts/Manrope-latin.woff2 +0 -0
- package/dist/theme-packs/scandi/fonts/OFL.txt +94 -0
- package/dist/theme-packs/scandi/fonts/SplineSansMono-latin.woff2 +0 -0
- package/dist/theme-packs/scandi/meta.json +37 -0
- package/dist/theme-packs/scandi/pack.css +370 -0
- package/dist/theme-packs/sumi/meta.json +1 -1
- package/dist/theme-packs/sumi/pack.css +4 -1
- package/dist/theme-packs/swissgrid/pack.css +4 -0
- package/dist/theme-packs/tidepool/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
- package/dist/theme-packs/tidepool/fonts/JetBrainsMono-latin.woff2 +0 -0
- package/dist/theme-packs/tidepool/fonts/OFL.txt +94 -0
- package/dist/theme-packs/tidepool/fonts/SpaceGrotesk-latin.woff2 +0 -0
- package/dist/theme-packs/tidepool/meta.json +37 -0
- package/dist/theme-packs/tidepool/pack.css +425 -0
- package/dist/theme-packs/timberline/fonts/Fraunces-italic-latin.woff2 +0 -0
- package/dist/theme-packs/timberline/fonts/Fraunces-latin.woff2 +0 -0
- package/dist/theme-packs/timberline/fonts/JetBrainsMono-latin.woff2 +0 -0
- package/dist/theme-packs/timberline/fonts/OFL.txt +95 -0
- package/dist/theme-packs/timberline/fonts/SourceSans3-italic-latin.woff2 +0 -0
- package/dist/theme-packs/timberline/fonts/SourceSans3-latin.woff2 +0 -0
- package/dist/theme-packs/timberline/meta.json +38 -0
- package/dist/theme-packs/timberline/pack.css +509 -0
- package/dist/theme-packs/washi/meta.json +1 -1
- package/dist/theme-packs/washi/pack.css +6 -26
- package/dist/theme-packs-registry/validator.js +24 -1
- package/dist/theme.css +1 -1
- package/eject/doc-history/index.tsx +1 -1
- package/eject/doc-pager/index.tsx +2 -2
- package/eject/header/header.tsx +16 -8
- package/eject/header/nav-class-tokens.ts +115 -0
- package/eject/header/nav-overflow-script.ts +49 -16
- package/eject/sidebar-tree-island/index.tsx +4 -4
- package/package.json +16 -13
- package/routes-src/index.tsx +10 -3
- package/routes-src/locale-index.tsx +9 -2
|
@@ -14,6 +14,7 @@ export interface DocHistoryMetaEntry {
|
|
|
14
14
|
/** Settings subset read by the DocHistoryArea factory. */
|
|
15
15
|
export interface DocHistoryAreaSettings {
|
|
16
16
|
docHistory: boolean;
|
|
17
|
+
docHistoryExclude?: string[];
|
|
17
18
|
bodyFootUtilArea: {
|
|
18
19
|
viewSourceLink?: boolean;
|
|
19
20
|
} | false | undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
2
2
|
import { Island } from "@takazudo/zfb";
|
|
3
|
+
import { compileExclude } from "@takazudo/zudo-doc-history-server/exclude";
|
|
3
4
|
import { BodyFootUtilArea } from "../body-foot-util/index.js";
|
|
4
5
|
import { toHistorySlug } from "../slug/index.js";
|
|
5
6
|
import { buildGitHubSourceUrl as buildGitHubSourceUrlBase } from "../github-helpers/index.js";
|
|
@@ -8,6 +9,7 @@ import { assertChromeContext } from "../chrome/assert-chrome-context.js";
|
|
|
8
9
|
function createDocHistoryArea(ctx) {
|
|
9
10
|
assertChromeContext(ctx, "createDocHistoryArea");
|
|
10
11
|
const settings = ctx.settings;
|
|
12
|
+
const isHistoryExcluded = compileExclude(settings.docHistoryExclude ?? []);
|
|
11
13
|
const defaultLocale = ctx.defaultLocale;
|
|
12
14
|
const docHistoryMeta = ctx.hostBindings.docHistoryMeta ?? {};
|
|
13
15
|
const t = ctx.t;
|
|
@@ -28,6 +30,7 @@ function createDocHistoryArea(ctx) {
|
|
|
28
30
|
}) {
|
|
29
31
|
if (!settings.docHistory) return null;
|
|
30
32
|
const historySlug = toHistorySlug(slug);
|
|
33
|
+
if (isHistoryExcluded(historySlug)) return null;
|
|
31
34
|
const effectiveHistoryLocale = isFallback ? defaultLocale : locale;
|
|
32
35
|
const composedSlug = effectiveHistoryLocale === defaultLocale ? historySlug : `${effectiveHistoryLocale}/${historySlug}`;
|
|
33
36
|
const meta = docHistoryMeta[composedSlug];
|
|
@@ -133,7 +133,7 @@ function createDocPageShell(ctx) {
|
|
|
133
133
|
Fragment (not <div>) so children become direct children of
|
|
134
134
|
<article class="zd-content">, picking up the flow-space rule. */
|
|
135
135
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
136
|
-
/* @__PURE__ */ jsx("h1", { class: "text-heading font-bold mb-vsp-xs", children: autoIndexLabel }),
|
|
136
|
+
/* @__PURE__ */ jsx("h1", { class: "text-heading font-bold border-b border-fg pb-vsp-xs mb-vsp-xs", children: autoIndexLabel }),
|
|
137
137
|
metainfoSlot,
|
|
138
138
|
description && /* @__PURE__ */ jsx("p", { class: "mb-vsp-lg text-title text-muted", "data-doc-description": true, children: description }),
|
|
139
139
|
/* @__PURE__ */ jsx(NavCardGrid, { children: autoIndexChildren ?? [] })
|
package/dist/doc-pager/index.js
CHANGED
|
@@ -12,7 +12,7 @@ function createDocPager(ctx) {
|
|
|
12
12
|
href: prev.href,
|
|
13
13
|
class: "group border border-muted rounded-lg p-hsp-lg hover:border-accent",
|
|
14
14
|
children: [
|
|
15
|
-
/* @__PURE__ */ jsxs("div", { class: "flex items-center gap-hsp-xs text-caption text-muted mb-vsp-2xs", children: [
|
|
15
|
+
/* @__PURE__ */ jsxs("div", { class: "flex items-center gap-hsp-xs text-caption text-muted mb-vsp-2xs group-hover:text-accent group-focus-visible:text-accent", children: [
|
|
16
16
|
/* @__PURE__ */ jsx(ChevronLeft, { className: "h-[1.125rem] w-[1.125rem]" }),
|
|
17
17
|
/* @__PURE__ */ jsx("span", { class: "no-underline", children: t("nav.previous", locale) })
|
|
18
18
|
] }),
|
|
@@ -26,7 +26,7 @@ function createDocPager(ctx) {
|
|
|
26
26
|
href: next.href,
|
|
27
27
|
class: "group border border-muted rounded-lg p-hsp-lg hover:border-accent text-right",
|
|
28
28
|
children: [
|
|
29
|
-
/* @__PURE__ */ jsxs("div", { class: "flex items-center justify-end gap-hsp-xs text-caption text-muted mb-vsp-2xs", children: [
|
|
29
|
+
/* @__PURE__ */ jsxs("div", { class: "flex items-center justify-end gap-hsp-xs text-caption text-muted mb-vsp-2xs group-hover:text-accent group-focus-visible:text-accent", children: [
|
|
30
30
|
/* @__PURE__ */ jsx("span", { class: "no-underline", children: t("nav.next", locale) }),
|
|
31
31
|
/* @__PURE__ */ jsx(ChevronRight, { className: "h-[1.125rem] w-[1.125rem]" })
|
|
32
32
|
] }),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type TopLevelMember } from "../theme-cli/config-scanner.js";
|
|
2
|
+
export interface ParsedZudoDocConfig {
|
|
3
|
+
ok: true;
|
|
4
|
+
members: TopLevelMember[];
|
|
5
|
+
/** Index of the zudoDoc({ ... }) call's opening `{`. */
|
|
6
|
+
braceOpenIdx: number;
|
|
7
|
+
/** Index of the matching closing `}`. */
|
|
8
|
+
braceCloseIdx: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ParsedZudoDocConfigRefusal {
|
|
11
|
+
ok: false;
|
|
12
|
+
/** Human-readable WHY, with no field-specific hint appended — callers own
|
|
13
|
+
* wording their own remediation (a read-only lookup vs. a write refusal
|
|
14
|
+
* need different follow-up text). */
|
|
15
|
+
reason: string;
|
|
16
|
+
}
|
|
17
|
+
export type ParseZudoDocConfigResult = ParsedZudoDocConfig | ParsedZudoDocConfigRefusal;
|
|
18
|
+
/**
|
|
19
|
+
* Locate and validate the project's `zfb.config.ts` canonical shape — a
|
|
20
|
+
* single `zudoDoc({ ... })` call whose sole argument is a literal,
|
|
21
|
+
* non-spread object — and return its top-level members. Mirrors
|
|
22
|
+
* `theme-cli/config-rewriter.ts#applyThemePackToConfigSource`'s validation
|
|
23
|
+
* exactly, generalized to any caller field.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseZudoDocConfigMembers(source: string): ParseZudoDocConfigResult;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigSyntaxError,
|
|
3
|
+
findMatchingBrace,
|
|
4
|
+
findZudoDocCallParens,
|
|
5
|
+
skipWhitespaceAndComments,
|
|
6
|
+
splitTopLevelMembers
|
|
7
|
+
} from "../theme-cli/config-scanner.js";
|
|
8
|
+
function parseZudoDocConfigMembers(source) {
|
|
9
|
+
let calls;
|
|
10
|
+
try {
|
|
11
|
+
calls = findZudoDocCallParens(source);
|
|
12
|
+
} catch (err) {
|
|
13
|
+
return { ok: false, reason: `could not parse zfb.config.ts (${err.message}).` };
|
|
14
|
+
}
|
|
15
|
+
if (calls.length === 0) {
|
|
16
|
+
return {
|
|
17
|
+
ok: false,
|
|
18
|
+
reason: "no zudoDoc(...) call found in zfb.config.ts. This CLI only reads/rewrites the canonical generated shape: export default defineConfig(zudoDoc({ ... }))."
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (calls.length > 1) {
|
|
22
|
+
return {
|
|
23
|
+
ok: false,
|
|
24
|
+
reason: `found ${calls.length} zudoDoc(...) call sites in zfb.config.ts \u2014 cannot safely determine which one to use.`
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const openParenIdx = calls[0];
|
|
28
|
+
let braceOpenIdx;
|
|
29
|
+
let braceCloseIdx;
|
|
30
|
+
let afterBrace;
|
|
31
|
+
try {
|
|
32
|
+
braceOpenIdx = skipWhitespaceAndComments(source, openParenIdx + 1);
|
|
33
|
+
if (source[braceOpenIdx] !== "{") {
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
reason: "zudoDoc(...) is not called with a plain object literal (found a computed or non-literal argument instead of zudoDoc({ ... })). This CLI only reads/rewrites the canonical generated shape."
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
braceCloseIdx = findMatchingBrace(source, braceOpenIdx);
|
|
40
|
+
afterBrace = skipWhitespaceAndComments(source, braceCloseIdx + 1);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
return { ok: false, reason: `could not parse zfb.config.ts (${err.message}).` };
|
|
43
|
+
}
|
|
44
|
+
const afterOptionalComma = source[afterBrace] === "," ? skipWhitespaceAndComments(source, afterBrace + 1) : afterBrace;
|
|
45
|
+
if (source[afterOptionalComma] !== ")") {
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
reason: "zudoDoc(...) is called with more than one argument \u2014 not the canonical single-object-literal shape."
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
let members;
|
|
52
|
+
try {
|
|
53
|
+
members = splitTopLevelMembers(source, braceOpenIdx + 1, braceCloseIdx);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
return { ok: false, reason: `could not parse zfb.config.ts (${err.message}).` };
|
|
56
|
+
}
|
|
57
|
+
const spread = members.find((m) => m.isSpread);
|
|
58
|
+
if (spread) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
reason: "zudoDoc({ ...spread }) uses a spread argument \u2014 not the canonical generated shape. This CLI only reads/rewrites a literal, hand-editable field list."
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return { ok: true, members, braceOpenIdx, braceCloseIdx };
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
parseZudoDocConfigMembers
|
|
68
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const EJECTED_LOGO_VALUE = "/img/logo.svg";
|
|
2
|
+
export interface ApplyLogoFieldToSourceOk {
|
|
3
|
+
ok: true;
|
|
4
|
+
/** The full rewritten file contents. Identical to the input when
|
|
5
|
+
* `changed` is false (idempotent re-run of an already-ejected logo). */
|
|
6
|
+
source: string;
|
|
7
|
+
changed: boolean;
|
|
8
|
+
mode: "replaced" | "inserted-after-site-name" | "inserted-first";
|
|
9
|
+
}
|
|
10
|
+
export interface ApplyLogoFieldToSourceRefusal {
|
|
11
|
+
ok: false;
|
|
12
|
+
/** Human-readable WHY, ending with the manual one-liner to add by hand.
|
|
13
|
+
* The input source is never touched when this is returned. */
|
|
14
|
+
reason: string;
|
|
15
|
+
}
|
|
16
|
+
export type ApplyLogoFieldToSourceResult = ApplyLogoFieldToSourceOk | ApplyLogoFieldToSourceRefusal;
|
|
17
|
+
/**
|
|
18
|
+
* Apply `logo: "/img/logo.svg"` to a `zfb.config.ts` source string. Pure and
|
|
19
|
+
* filesystem-free — callers own reading/writing the actual file (see
|
|
20
|
+
* `eject.ts`).
|
|
21
|
+
*/
|
|
22
|
+
export declare function applyLogoFieldToConfigSource(source: string): ApplyLogoFieldToSourceResult;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { isPlainStringLiteralSpan } from "../theme-cli/config-scanner.js";
|
|
2
|
+
import { parseZudoDocConfigMembers } from "./config-parse.js";
|
|
3
|
+
const EJECTED_LOGO_VALUE = "/img/logo.svg";
|
|
4
|
+
function manualHint() {
|
|
5
|
+
return `Add the field manually inside your zudoDoc({ ... }) call: logo: ${JSON.stringify(EJECTED_LOGO_VALUE)},`;
|
|
6
|
+
}
|
|
7
|
+
function refuse(reason) {
|
|
8
|
+
return { ok: false, reason: `${reason} ${manualHint()}` };
|
|
9
|
+
}
|
|
10
|
+
function isPlainFalseLiteralSpan(source, start, end) {
|
|
11
|
+
return source.slice(start, end).trim() === "false";
|
|
12
|
+
}
|
|
13
|
+
function detectIndent(source, members) {
|
|
14
|
+
const ref = members[0];
|
|
15
|
+
const refPos = ref ? ref.keyStart ?? ref.memberStart : null;
|
|
16
|
+
if (refPos !== null && refPos !== void 0) {
|
|
17
|
+
const newlineIdx = source.lastIndexOf("\n", refPos);
|
|
18
|
+
const lineStart = newlineIdx === -1 ? 0 : newlineIdx + 1;
|
|
19
|
+
const line = source.slice(lineStart, refPos);
|
|
20
|
+
if (/^[ \t]*$/.test(line) && line.length > 0) return line;
|
|
21
|
+
}
|
|
22
|
+
return " ";
|
|
23
|
+
}
|
|
24
|
+
function applyLogoFieldToConfigSource(source) {
|
|
25
|
+
const parsed = parseZudoDocConfigMembers(source);
|
|
26
|
+
if (!parsed.ok) return refuse(parsed.reason);
|
|
27
|
+
const { members, braceOpenIdx } = parsed;
|
|
28
|
+
const newValueLiteral = JSON.stringify(EJECTED_LOGO_VALUE);
|
|
29
|
+
const logoMembers = members.filter((m) => m.key === "logo");
|
|
30
|
+
if (logoMembers.length > 1) {
|
|
31
|
+
return refuse(
|
|
32
|
+
'zfb.config.ts declares "logo" more than once inside zudoDoc({ ... }). This CLI only rewrites a single canonical field; remove the duplicate and re-run.'
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
const logoMember = logoMembers[0];
|
|
36
|
+
if (logoMember) {
|
|
37
|
+
if (logoMember.valueStart === null || logoMember.valueEnd === null) {
|
|
38
|
+
return refuse('the existing "logo" field in zfb.config.ts is not a simple `key: value` property this CLI understands.');
|
|
39
|
+
}
|
|
40
|
+
const isReplaceableLiteral = isPlainStringLiteralSpan(source, logoMember.valueStart, logoMember.valueEnd) || isPlainFalseLiteralSpan(source, logoMember.valueStart, logoMember.valueEnd);
|
|
41
|
+
if (!isReplaceableLiteral) {
|
|
42
|
+
return refuse(
|
|
43
|
+
'the existing "logo" field\'s value is not a plain string literal or `false` \u2014 cannot safely rewrite it without risking corruption.'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const newSource2 = source.slice(0, logoMember.valueStart) + newValueLiteral + source.slice(logoMember.valueEnd);
|
|
47
|
+
return { ok: true, source: newSource2, changed: newSource2 !== source, mode: "replaced" };
|
|
48
|
+
}
|
|
49
|
+
const siteNameMember = members.find((m) => m.key === "siteName");
|
|
50
|
+
const indent = detectIndent(source, members);
|
|
51
|
+
if (siteNameMember) {
|
|
52
|
+
const insertAt2 = siteNameMember.commaIndex !== null ? siteNameMember.commaIndex + 1 : siteNameMember.memberEnd;
|
|
53
|
+
const prefix = siteNameMember.commaIndex !== null ? "" : ",";
|
|
54
|
+
const insertText2 = `${prefix}
|
|
55
|
+
${indent}logo: ${newValueLiteral},`;
|
|
56
|
+
const newSource2 = source.slice(0, insertAt2) + insertText2 + source.slice(insertAt2);
|
|
57
|
+
return { ok: true, source: newSource2, changed: true, mode: "inserted-after-site-name" };
|
|
58
|
+
}
|
|
59
|
+
const insertAt = braceOpenIdx + 1;
|
|
60
|
+
const insertText = `
|
|
61
|
+
${indent}logo: ${newValueLiteral},`;
|
|
62
|
+
const newSource = source.slice(0, insertAt) + insertText + source.slice(insertAt);
|
|
63
|
+
return { ok: true, source: newSource, changed: true, mode: "inserted-first" };
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
EJECTED_LOGO_VALUE,
|
|
67
|
+
applyLogoFieldToConfigSource
|
|
68
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface EjectLogoOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
/** Explicit seed override (already validated non-empty by the CLI arg
|
|
4
|
+
* parser in bin/zudo-doc.mjs). When omitted, the seed is resolved from
|
|
5
|
+
* zfb.config.ts's siteName field. */
|
|
6
|
+
seed?: string;
|
|
7
|
+
force?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface EjectLogoResult {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
/** Human-readable outcome message (success confirmation, or a refusal
|
|
12
|
+
* explaining WHY). */
|
|
13
|
+
message: string;
|
|
14
|
+
/** True when the SVG was written but the config rewrite was refused — a
|
|
15
|
+
* nonzero-exit partial success, not a total failure. */
|
|
16
|
+
partial?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare function ejectLogo(options?: EjectLogoOptions): Promise<EjectLogoResult>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { renderAutoLogoStandaloneSvg } from "../auto-logo/standalone.js";
|
|
4
|
+
import { applyLogoFieldToConfigSource } from "./config-rewriter.js";
|
|
5
|
+
import { resolveSiteNameFromConfigSource } from "./site-name.js";
|
|
6
|
+
const ZFB_CONFIG_FILENAME = "zfb.config.ts";
|
|
7
|
+
const LOGO_RELATIVE_PATH = path.join("public", "img", "logo.svg");
|
|
8
|
+
const DEFAULT_SEED = "Docs";
|
|
9
|
+
async function ejectLogo(options = {}) {
|
|
10
|
+
const cwd = options.cwd ?? process.cwd();
|
|
11
|
+
const force = options.force ?? false;
|
|
12
|
+
const configPath = path.join(cwd, ZFB_CONFIG_FILENAME);
|
|
13
|
+
if (!await fs.pathExists(configPath)) {
|
|
14
|
+
return {
|
|
15
|
+
ok: false,
|
|
16
|
+
message: `zfb.config.ts not found at ${configPath}.
|
|
17
|
+
Run this command from your project root.`
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const source = await fs.readFile(configPath, "utf8");
|
|
21
|
+
let seed;
|
|
22
|
+
if (options.seed) {
|
|
23
|
+
seed = options.seed;
|
|
24
|
+
} else {
|
|
25
|
+
const resolution = resolveSiteNameFromConfigSource(source);
|
|
26
|
+
if (resolution.kind === "unresolvable") {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
message: `Could not determine a logo seed from zfb.config.ts: ${resolution.reason}
|
|
30
|
+
Pass --seed <name> to specify the logo seed explicitly.`
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
seed = resolution.kind === "literal" ? resolution.value : DEFAULT_SEED;
|
|
34
|
+
}
|
|
35
|
+
const rewriteResult = applyLogoFieldToConfigSource(source);
|
|
36
|
+
const svgPath = path.join(cwd, LOGO_RELATIVE_PATH);
|
|
37
|
+
if (!force && await fs.pathExists(svgPath)) {
|
|
38
|
+
return {
|
|
39
|
+
ok: false,
|
|
40
|
+
message: `${LOGO_RELATIVE_PATH} already exists.
|
|
41
|
+
Pass --force to overwrite it.`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const svg = renderAutoLogoStandaloneSvg(seed);
|
|
45
|
+
await fs.ensureDir(path.dirname(svgPath));
|
|
46
|
+
await fs.writeFile(svgPath, svg, "utf8");
|
|
47
|
+
if (!rewriteResult.ok) {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
partial: true,
|
|
51
|
+
message: `Wrote ${LOGO_RELATIVE_PATH}, but could not update zfb.config.ts: ${rewriteResult.reason}`
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (rewriteResult.changed) {
|
|
55
|
+
await fs.writeFile(configPath, rewriteResult.source, "utf8");
|
|
56
|
+
}
|
|
57
|
+
const verb = rewriteResult.changed ? "Ejected logo" : "Ejected logo (field already set)";
|
|
58
|
+
return {
|
|
59
|
+
ok: true,
|
|
60
|
+
message: `${verb} \u2192 ${LOGO_RELATIVE_PATH}
|
|
61
|
+
Updated zfb.config.ts's logo field.`
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
ejectLogo
|
|
66
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ejectLogo, type EjectLogoOptions, type EjectLogoResult } from "./eject.js";
|
|
2
|
+
export { applyLogoFieldToConfigSource, EJECTED_LOGO_VALUE, type ApplyLogoFieldToSourceOk, type ApplyLogoFieldToSourceRefusal, type ApplyLogoFieldToSourceResult, } from "./config-rewriter.js";
|
|
3
|
+
export { resolveSiteNameFromConfigSource, type SiteNameResolution } from "./site-name.js";
|
|
4
|
+
export { parseZudoDocConfigMembers, type ParsedZudoDocConfig, type ParsedZudoDocConfigRefusal, type ParseZudoDocConfigResult, } from "./config-parse.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ejectLogo } from "./eject.js";
|
|
2
|
+
import {
|
|
3
|
+
applyLogoFieldToConfigSource,
|
|
4
|
+
EJECTED_LOGO_VALUE
|
|
5
|
+
} from "./config-rewriter.js";
|
|
6
|
+
import { resolveSiteNameFromConfigSource } from "./site-name.js";
|
|
7
|
+
import {
|
|
8
|
+
parseZudoDocConfigMembers
|
|
9
|
+
} from "./config-parse.js";
|
|
10
|
+
export {
|
|
11
|
+
EJECTED_LOGO_VALUE,
|
|
12
|
+
applyLogoFieldToConfigSource,
|
|
13
|
+
ejectLogo,
|
|
14
|
+
parseZudoDocConfigMembers,
|
|
15
|
+
resolveSiteNameFromConfigSource
|
|
16
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type SiteNameResolution = {
|
|
2
|
+
kind: "literal";
|
|
3
|
+
value: string;
|
|
4
|
+
} | {
|
|
5
|
+
kind: "absent";
|
|
6
|
+
} | {
|
|
7
|
+
kind: "unresolvable";
|
|
8
|
+
reason: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Resolve `siteName` from a `zfb.config.ts` source string.
|
|
12
|
+
*
|
|
13
|
+
* - Literal `siteName: "..."` → `{ kind: "literal", value }`.
|
|
14
|
+
* - Canonical literal config with no `siteName` field → `{ kind: "absent" }`
|
|
15
|
+
* (the runtime default `"Docs"` genuinely applies — this IS a confirmed
|
|
16
|
+
* reading, the caller decides the default value).
|
|
17
|
+
* - Anything else (no/duplicate zudoDoc call, spread argument, computed or
|
|
18
|
+
* duplicate `siteName`, non-string value) → `{ kind: "unresolvable",
|
|
19
|
+
* reason }`; the caller must require `--seed`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveSiteNameFromConfigSource(source: string): SiteNameResolution;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isPlainStringLiteralSpan, unquoteStringLiteralSpan } from "../theme-cli/config-scanner.js";
|
|
2
|
+
import { parseZudoDocConfigMembers } from "./config-parse.js";
|
|
3
|
+
function resolveSiteNameFromConfigSource(source) {
|
|
4
|
+
const parsed = parseZudoDocConfigMembers(source);
|
|
5
|
+
if (!parsed.ok) return { kind: "unresolvable", reason: parsed.reason };
|
|
6
|
+
const siteNameMembers = parsed.members.filter((m) => m.key === "siteName");
|
|
7
|
+
if (siteNameMembers.length > 1) {
|
|
8
|
+
return {
|
|
9
|
+
kind: "unresolvable",
|
|
10
|
+
reason: 'zfb.config.ts declares "siteName" more than once inside zudoDoc({ ... }) \u2014 cannot safely determine which one the runtime reads.'
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const member = siteNameMembers[0];
|
|
14
|
+
if (!member) return { kind: "absent" };
|
|
15
|
+
if (member.valueStart === null || member.valueEnd === null) {
|
|
16
|
+
return {
|
|
17
|
+
kind: "unresolvable",
|
|
18
|
+
reason: 'the "siteName" field in zfb.config.ts is not a simple `key: value` property this CLI understands.'
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
if (!isPlainStringLiteralSpan(source, member.valueStart, member.valueEnd)) {
|
|
22
|
+
return {
|
|
23
|
+
kind: "unresolvable",
|
|
24
|
+
reason: `the "siteName" field's value in zfb.config.ts is not a plain string literal.`
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return { kind: "literal", value: unquoteStringLiteralSpan(source, member.valueStart, member.valueEnd) };
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
resolveSiteNameFromConfigSource
|
|
31
|
+
};
|
package/dist/features.css
CHANGED
|
@@ -179,31 +179,10 @@ header[data-header] {
|
|
|
179
179
|
--zfb-hi-hd: var(--zd-syntax-keyword);
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
/*
|
|
183
|
-
* through
|
|
184
|
-
*
|
|
185
|
-
|
|
186
|
-
[data-theme] .shiki span {
|
|
187
|
-
color: light-dark(var(--shiki-light), var(--shiki-dark));
|
|
188
|
-
font-style: light-dark(
|
|
189
|
-
var(--shiki-light-font-style, inherit),
|
|
190
|
-
var(--shiki-dark-font-style, inherit)
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
/* Background only on the <pre> wrapper — deliberately NOT on token spans. The
|
|
195
|
-
* --shiki-*-bg vars are set inline on the <pre> and inherit down to spans;
|
|
196
|
-
* painting them per-span would lay an opaque base background over the
|
|
197
|
-
* translucent line-/word-highlight backgrounds that sit on the enclosing
|
|
198
|
-
* .line span (see .line.highlighted below). */
|
|
199
|
-
[data-theme] .shiki {
|
|
200
|
-
background-color: light-dark(var(--shiki-light-bg), var(--shiki-dark-bg));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/* HtmlPreview component — Shiki code blocks
|
|
204
|
-
* Token colors inherit from the global [data-theme] .shiki rule above.
|
|
205
|
-
* These rules only adjust layout and background for the preview context. */
|
|
206
|
-
.zd-html-preview-code pre.shiki {
|
|
182
|
+
/* HtmlPreview component — zfb semantic code blocks. Token colors and the root
|
|
183
|
+
* surface resolve through the shared class-mode bridge above; these rules only
|
|
184
|
+
* adjust layout for the preview context. */
|
|
185
|
+
.zd-html-preview-code pre.hi-root {
|
|
207
186
|
margin: 0;
|
|
208
187
|
padding: var(--spacing-hsp-md);
|
|
209
188
|
font-size: var(--text-caption);
|
|
@@ -211,7 +190,7 @@ header[data-header] {
|
|
|
211
190
|
overflow-x: auto;
|
|
212
191
|
}
|
|
213
192
|
|
|
214
|
-
.zd-html-preview-code pre.
|
|
193
|
+
.zd-html-preview-code pre.hi-root code {
|
|
215
194
|
font-family: var(--font-mono);
|
|
216
195
|
white-space: pre;
|
|
217
196
|
}
|
|
@@ -266,9 +245,9 @@ pre.hi-root .line .highlighted-word {
|
|
|
266
245
|
* zfb's :::code-group emits <CodeGroup tabs={[...]}> with one
|
|
267
246
|
* <pre data-lang="…">{RAW text}</pre> child per fence. These <pre> elements
|
|
268
247
|
* are NOT syntax-highlighted (the Rust pipeline doesn't highlight inside
|
|
269
|
-
* code-group fences), so they get no `.hi-root` class.
|
|
270
|
-
* code-block visual treatment via tokens to match the
|
|
271
|
-
* surrounding them.
|
|
248
|
+
* code-group fences), so they get no `.hi-root` class.
|
|
249
|
+
* Apply explicit code-block visual treatment via tokens to match the
|
|
250
|
+
* highlighted code blocks surrounding them.
|
|
272
251
|
* ======================================== */
|
|
273
252
|
|
|
274
253
|
.code-group-panel pre[data-lang] {
|
package/dist/header/header.js
CHANGED
|
@@ -6,6 +6,14 @@ import {
|
|
|
6
6
|
pathForMatch
|
|
7
7
|
} from "./nav-active.js";
|
|
8
8
|
import { NAV_OVERFLOW_SCRIPT } from "./nav-overflow-script.js";
|
|
9
|
+
import {
|
|
10
|
+
NAV_CHEVRON_ACTIVE,
|
|
11
|
+
NAV_CHEVRON_INACTIVE,
|
|
12
|
+
NAV_CHILD_ACTIVE,
|
|
13
|
+
NAV_CHILD_INACTIVE,
|
|
14
|
+
NAV_TOP_ACTIVE,
|
|
15
|
+
NAV_TOP_INACTIVE
|
|
16
|
+
} from "./nav-class-tokens.js";
|
|
9
17
|
import { LANGUAGE_SWITCHER_INIT_SCRIPT } from "../i18n-version/language-switcher.js";
|
|
10
18
|
import { VERSION_SWITCHER_REWIRE_SCRIPT } from "../i18n-version/version-switcher.js";
|
|
11
19
|
import { GitHub as GitHubIcon } from "../icons/index.js";
|
|
@@ -81,7 +89,7 @@ function Header(props) {
|
|
|
81
89
|
"button",
|
|
82
90
|
{
|
|
83
91
|
type: "button",
|
|
84
|
-
class: "px-hsp-md py-vsp-2xs text-small font-medium text-muted hover:underline cursor-pointer",
|
|
92
|
+
class: "px-hsp-md py-vsp-2xs text-small font-medium text-muted hover:text-accent hover:underline focus-visible:text-accent focus-visible:underline cursor-pointer",
|
|
85
93
|
"data-nav-more-toggle": true,
|
|
86
94
|
"aria-expanded": "false",
|
|
87
95
|
children: "\xB7\xB7\xB7"
|
|
@@ -177,7 +185,7 @@ function renderNavItem(item, activeNavPath, activeCategory, lang, currentVersion
|
|
|
177
185
|
"aria-expanded": "false",
|
|
178
186
|
class: [
|
|
179
187
|
"flex items-center gap-x-hsp-xs px-hsp-md py-vsp-2xs text-small font-medium transition-colors",
|
|
180
|
-
isActive ? "
|
|
188
|
+
isActive ? NAV_TOP_ACTIVE.join(" ") : NAV_TOP_INACTIVE.join(" ")
|
|
181
189
|
].join(" "),
|
|
182
190
|
children: [
|
|
183
191
|
label,
|
|
@@ -186,7 +194,7 @@ function renderNavItem(item, activeNavPath, activeCategory, lang, currentVersion
|
|
|
186
194
|
{
|
|
187
195
|
class: [
|
|
188
196
|
"h-[0.5rem] w-[0.5rem] shrink-0",
|
|
189
|
-
isActive ? "
|
|
197
|
+
isActive ? NAV_CHEVRON_ACTIVE.join(" ") : NAV_CHEVRON_INACTIVE.join(" ")
|
|
190
198
|
].join(" "),
|
|
191
199
|
fill: "none",
|
|
192
200
|
viewBox: "0 0 24 24",
|
|
@@ -216,8 +224,8 @@ function renderNavItem(item, activeNavPath, activeCategory, lang, currentVersion
|
|
|
216
224
|
href: childHref,
|
|
217
225
|
"data-active": childActive ? "" : void 0,
|
|
218
226
|
class: [
|
|
219
|
-
"block px-hsp-md py-vsp-2xs text-small hover:bg-accent/10 hover:underline",
|
|
220
|
-
childActive ? "
|
|
227
|
+
"block px-hsp-md py-vsp-2xs text-small hover:bg-accent/10 hover:underline focus-visible:underline",
|
|
228
|
+
childActive ? NAV_CHILD_ACTIVE.join(" ") : NAV_CHILD_INACTIVE.join(" ")
|
|
221
229
|
].join(" "),
|
|
222
230
|
children: childLabel
|
|
223
231
|
}
|
|
@@ -235,7 +243,7 @@ function renderNavItem(item, activeNavPath, activeCategory, lang, currentVersion
|
|
|
235
243
|
"data-nav-item": true,
|
|
236
244
|
class: [
|
|
237
245
|
"px-hsp-md py-vsp-2xs text-small font-medium transition-colors shrink-0",
|
|
238
|
-
isActive ? "
|
|
246
|
+
isActive ? NAV_TOP_ACTIVE.join(" ") : NAV_TOP_INACTIVE.join(" ")
|
|
239
247
|
].join(" "),
|
|
240
248
|
children: label
|
|
241
249
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const NAV_TOP_ACTIVE: readonly string[];
|
|
2
|
+
export declare const NAV_TOP_INACTIVE: readonly string[];
|
|
3
|
+
export declare const NAV_CHEVRON_ACTIVE: readonly string[];
|
|
4
|
+
export declare const NAV_CHEVRON_INACTIVE: readonly string[];
|
|
5
|
+
export declare const NAV_CHILD_ACTIVE: readonly string[];
|
|
6
|
+
export declare const NAV_CHILD_INACTIVE: readonly string[];
|
|
7
|
+
export declare const NAV_MENU_PARENT: readonly string[];
|
|
8
|
+
export declare const NAV_MENU_PARENT_ACTIVE_SUFFIX: readonly string[];
|
|
9
|
+
export declare const NAV_MENU_PLAIN: readonly string[];
|
|
10
|
+
export declare const NAV_MENU_PLAIN_ACTIVE_SUFFIX: readonly string[];
|
|
11
|
+
export declare const NAV_MENU_CHILD_ACTIVE: readonly string[];
|
|
12
|
+
export declare const NAV_MENU_CHILD_INACTIVE: readonly string[];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const NAV_TOP_ACTIVE = ["bg-fg", "text-bg"];
|
|
2
|
+
const NAV_TOP_INACTIVE = [
|
|
3
|
+
"text-muted",
|
|
4
|
+
"hover:text-accent",
|
|
5
|
+
"hover:underline",
|
|
6
|
+
"focus:underline",
|
|
7
|
+
"focus:text-accent"
|
|
8
|
+
];
|
|
9
|
+
const NAV_CHEVRON_ACTIVE = ["text-bg"];
|
|
10
|
+
const NAV_CHEVRON_INACTIVE = ["text-muted"];
|
|
11
|
+
const NAV_CHILD_ACTIVE = ["font-bold", "text-accent"];
|
|
12
|
+
const NAV_CHILD_INACTIVE = [
|
|
13
|
+
"text-fg",
|
|
14
|
+
"hover:text-accent",
|
|
15
|
+
"focus-visible:text-accent"
|
|
16
|
+
];
|
|
17
|
+
const MENU_ROW_BASE = [
|
|
18
|
+
"block",
|
|
19
|
+
"px-hsp-md",
|
|
20
|
+
"py-vsp-2xs",
|
|
21
|
+
"text-small"
|
|
22
|
+
];
|
|
23
|
+
const MENU_CHILD_BASE = [
|
|
24
|
+
"block",
|
|
25
|
+
"pl-hsp-xl",
|
|
26
|
+
"pr-hsp-md",
|
|
27
|
+
"py-vsp-2xs",
|
|
28
|
+
"text-small"
|
|
29
|
+
];
|
|
30
|
+
const MENU_ROW_RESTING = [
|
|
31
|
+
"hover:bg-accent/10",
|
|
32
|
+
"hover:underline",
|
|
33
|
+
"focus-visible:underline",
|
|
34
|
+
"focus-visible:text-accent",
|
|
35
|
+
"text-fg",
|
|
36
|
+
"hover:text-accent"
|
|
37
|
+
];
|
|
38
|
+
const NAV_MENU_PARENT = [
|
|
39
|
+
...MENU_ROW_BASE,
|
|
40
|
+
"font-bold",
|
|
41
|
+
...MENU_ROW_RESTING
|
|
42
|
+
];
|
|
43
|
+
const NAV_MENU_PARENT_ACTIVE_SUFFIX = ["text-accent"];
|
|
44
|
+
const NAV_MENU_PLAIN = [
|
|
45
|
+
...MENU_ROW_BASE,
|
|
46
|
+
...MENU_ROW_RESTING
|
|
47
|
+
];
|
|
48
|
+
const NAV_MENU_PLAIN_ACTIVE_SUFFIX = [
|
|
49
|
+
...NAV_CHILD_ACTIVE
|
|
50
|
+
];
|
|
51
|
+
const NAV_MENU_CHILD_ACTIVE = [
|
|
52
|
+
...MENU_CHILD_BASE,
|
|
53
|
+
...NAV_CHILD_ACTIVE,
|
|
54
|
+
"hover:bg-accent/10",
|
|
55
|
+
"hover:underline",
|
|
56
|
+
"focus-visible:underline"
|
|
57
|
+
];
|
|
58
|
+
const NAV_MENU_CHILD_INACTIVE = [
|
|
59
|
+
...MENU_CHILD_BASE,
|
|
60
|
+
"text-fg",
|
|
61
|
+
"hover:bg-accent/10",
|
|
62
|
+
"hover:text-accent",
|
|
63
|
+
"hover:underline",
|
|
64
|
+
"focus-visible:underline",
|
|
65
|
+
"focus-visible:text-accent"
|
|
66
|
+
];
|
|
67
|
+
export {
|
|
68
|
+
NAV_CHEVRON_ACTIVE,
|
|
69
|
+
NAV_CHEVRON_INACTIVE,
|
|
70
|
+
NAV_CHILD_ACTIVE,
|
|
71
|
+
NAV_CHILD_INACTIVE,
|
|
72
|
+
NAV_MENU_CHILD_ACTIVE,
|
|
73
|
+
NAV_MENU_CHILD_INACTIVE,
|
|
74
|
+
NAV_MENU_PARENT,
|
|
75
|
+
NAV_MENU_PARENT_ACTIVE_SUFFIX,
|
|
76
|
+
NAV_MENU_PLAIN,
|
|
77
|
+
NAV_MENU_PLAIN_ACTIVE_SUFFIX,
|
|
78
|
+
NAV_TOP_ACTIVE,
|
|
79
|
+
NAV_TOP_INACTIVE
|
|
80
|
+
};
|