@dogsbay/docs-layout 0.2.0-beta.10 → 0.2.0-beta.100
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/package.json +7 -5
- package/src/BlogIndex.astro +179 -0
- package/src/DocsFooter.astro +27 -3
- package/src/DocsLayout.astro +541 -40
- package/src/DocsNavClient.astro +107 -0
- package/src/DocsToc.astro +1 -1
- package/src/SearchDialog.astro +301 -33
- package/src/TagList.astro +17 -2
- package/src/VersionSwitcher.astro +6 -0
- package/src/docs-nav-client.ts +419 -0
- package/src/json-ld.ts +112 -0
- package/src/link-icons.ts +54 -0
- package/src/markdown-negotiation.ts +38 -2
- package/src/nav-filter.ts +42 -129
- package/src/search-facets.ts +511 -9
- package/src/switcher.ts +83 -2
- package/src/toc-placement.ts +71 -0
- package/src/version-redirect.ts +23 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide which TOC container(s) and right-rail region `DocsLayout` renders,
|
|
3
|
+
* given the `toc` placement mode and per-page facts. Factored out of
|
|
4
|
+
* `DocsLayout.astro` so the branching logic is unit-testable (the .astro
|
|
5
|
+
* file just consumes the result) — same pattern as `nav-filter.ts` etc.
|
|
6
|
+
*
|
|
7
|
+
* See plans/ask-branch1-placement-toc.md.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type TocMode = "top" | "popover" | "rail" | "off";
|
|
11
|
+
|
|
12
|
+
export interface TocPlacement {
|
|
13
|
+
/** Classic right-hand TOC sidebar (the pre-`toc`-option layout). */
|
|
14
|
+
railToc: boolean;
|
|
15
|
+
/** Expandable "On this page" disclosure at the top of the article. */
|
|
16
|
+
topToc: boolean;
|
|
17
|
+
/** "On this page" dropdown in the header. */
|
|
18
|
+
popoverToc: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* The right-rail plugin region (host for the `right-rail` named slot, e.g.
|
|
21
|
+
* an Ask AI panel). Present whenever the rail isn't the classic TOC's, and
|
|
22
|
+
* deliberately NOT gated on headings — so a plugin can dock on heading-less
|
|
23
|
+
* pages. Never shown on wide/API pages (no rail there).
|
|
24
|
+
*/
|
|
25
|
+
regionRail: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Whether a page has enough displayable headings to warrant a TOC. The TOC
|
|
30
|
+
* (`DocsToc`) only lists depth `minDepth`–`maxDepth` (2–3 by default), so the
|
|
31
|
+
* page H1 never counts; and a TOC of a single entry isn't useful, so require
|
|
32
|
+
* `min` (2) by default. Pages like a landing/welcome page — H1 + prose, no
|
|
33
|
+
* sub-sections — therefore get no "On this page".
|
|
34
|
+
*/
|
|
35
|
+
export function hasDisplayableToc(
|
|
36
|
+
headings: { depth: number }[],
|
|
37
|
+
opts: { minDepth?: number; maxDepth?: number; min?: number } = {},
|
|
38
|
+
): boolean {
|
|
39
|
+
const { minDepth = 2, maxDepth = 3, min = 2 } = opts;
|
|
40
|
+
let count = 0;
|
|
41
|
+
for (const h of headings) {
|
|
42
|
+
if (h.depth >= minDepth && h.depth <= maxDepth) count++;
|
|
43
|
+
if (count >= min) return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface TocPlacementInput {
|
|
49
|
+
/** Page has at least one heading to list. */
|
|
50
|
+
hasHeadings: boolean;
|
|
51
|
+
/** Wide/API layout — composes its own columns, so no right rail. */
|
|
52
|
+
wideLayout: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the placement flags. A TOC container only renders when there are
|
|
57
|
+
* headings to show; the region rail is independent of headings. `rail` and
|
|
58
|
+
* the region rail are mutually exclusive (they compete for the same column),
|
|
59
|
+
* and both are suppressed on wide pages.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveTocPlacement(
|
|
62
|
+
toc: TocMode,
|
|
63
|
+
{ hasHeadings, wideLayout }: TocPlacementInput,
|
|
64
|
+
): TocPlacement {
|
|
65
|
+
return {
|
|
66
|
+
railToc: toc === "rail" && hasHeadings && !wideLayout,
|
|
67
|
+
topToc: toc === "top" && hasHeadings,
|
|
68
|
+
popoverToc: toc === "popover" && hasHeadings,
|
|
69
|
+
regionRail: toc !== "rail" && !wideLayout,
|
|
70
|
+
};
|
|
71
|
+
}
|
package/src/version-redirect.ts
CHANGED
|
@@ -35,6 +35,20 @@ export interface AxisRedirectConfig {
|
|
|
35
35
|
defaultLocale?: string;
|
|
36
36
|
/** Full set of declared locale ids. Empty/undefined → axis inactive. */
|
|
37
37
|
knownLocales?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* First-segment names that aren't locale/version-axis-prefixable
|
|
40
|
+
* — e.g. taxonomy index paths like `tags`, `by-type`, `by-status`.
|
|
41
|
+
* Taxonomy routes emit a single global namespace shared across
|
|
42
|
+
* all locales / versions (one `/tags/` for the whole site, not
|
|
43
|
+
* one per locale), so the axis-redirect helper must skip them.
|
|
44
|
+
* Without this skip, chip hrefs to `/<basePath>/tags/...` would
|
|
45
|
+
* 302 to `/<basePath>/<defaultLocale>/tags/...` which 404s.
|
|
46
|
+
*
|
|
47
|
+
* Each entry is the first URL segment after basePath
|
|
48
|
+
* (no leading slash). Sourced from declared
|
|
49
|
+
* `taxonomies.<name>.indexPath` in `dogsbay.config.yml`.
|
|
50
|
+
*/
|
|
51
|
+
globalPrefixes?: string[];
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
/**
|
|
@@ -88,6 +102,15 @@ export function shouldRedirectToDefaultVersion(
|
|
|
88
102
|
// Skip Astro / Pagefind asset paths.
|
|
89
103
|
if (segments[0].startsWith("_") || segments[0] === "pagefind") return null;
|
|
90
104
|
|
|
105
|
+
// Skip global-namespace prefixes (taxonomy index paths and similar
|
|
106
|
+
// routes that don't live under per-locale / per-version trees).
|
|
107
|
+
// Without this, chip hrefs to `/docs/tags/concept/rag/` get
|
|
108
|
+
// redirected to `/docs/<defaultLocale>/tags/concept/rag/` which
|
|
109
|
+
// 404s — the taxonomy routes are emitted once at the unprefixed
|
|
110
|
+
// path. See plans/beta-launch-followups.md.
|
|
111
|
+
const globalPrefixes = config.globalPrefixes ?? [];
|
|
112
|
+
if (globalPrefixes.includes(segments[0])) return null;
|
|
113
|
+
|
|
91
114
|
// Greedy axis detection — locale outermost, version next.
|
|
92
115
|
const knownLocales = new Set(config.knownLocales ?? []);
|
|
93
116
|
const knownVersions = new Set(config.knownVersions ?? []);
|