@barodoc/theme-docs 7.1.1 → 8.0.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/package.json +11 -4
- package/src/components/Breadcrumb.astro +13 -2
- package/src/components/MobileNav.astro +19 -13
- package/src/components/Sidebar.astro +19 -9
- package/src/layouts/DocsLayout.astro +5 -4
- package/src/layouts/PageLayout.astro +43 -0
- package/src/pages/[...page].astro +45 -0
- package/src/pages/blog/[...slug].astro +3 -3
- package/src/pages/blog/index.astro +1 -1
- package/src/pages/changelog/index.astro +2 -2
- package/src/pages/{docs → section}/[...slug].astro +56 -44
- package/src/theme.ts +7 -2
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barodoc/theme-docs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "Documentation theme for Barodoc",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.ts",
|
|
9
|
-
"./theme":
|
|
9
|
+
"./theme": {
|
|
10
|
+
"types": "./src/theme.ts",
|
|
11
|
+
"import": "./dist/theme.js"
|
|
12
|
+
},
|
|
10
13
|
"./components": "./src/components/index.ts",
|
|
11
14
|
"./components/*": "./src/components/*",
|
|
12
15
|
"./layouts/*": "./src/layouts/*",
|
|
@@ -15,7 +18,8 @@
|
|
|
15
18
|
"./lib/*": "./src/lib/*"
|
|
16
19
|
},
|
|
17
20
|
"files": [
|
|
18
|
-
"src"
|
|
21
|
+
"src",
|
|
22
|
+
"dist"
|
|
19
23
|
],
|
|
20
24
|
"dependencies": {
|
|
21
25
|
"@radix-ui/react-accordion": "^1.2.12",
|
|
@@ -36,7 +40,7 @@
|
|
|
36
40
|
"rehype-katex": "^7.0.1",
|
|
37
41
|
"remark-math": "^6.0.0",
|
|
38
42
|
"tailwind-merge": "^3.4.0",
|
|
39
|
-
"@barodoc/core": "
|
|
43
|
+
"@barodoc/core": "8.0.0"
|
|
40
44
|
},
|
|
41
45
|
"peerDependencies": {
|
|
42
46
|
"astro": "^5.0.0",
|
|
@@ -53,6 +57,7 @@
|
|
|
53
57
|
"@types/react-dom": "^19.0.0",
|
|
54
58
|
"astro": "^5.0.0",
|
|
55
59
|
"tailwindcss": "^4.0.0",
|
|
60
|
+
"tsup": "^8.3.0",
|
|
56
61
|
"typescript": "^5.7.0"
|
|
57
62
|
},
|
|
58
63
|
"keywords": [
|
|
@@ -69,6 +74,8 @@
|
|
|
69
74
|
"directory": "packages/theme-docs"
|
|
70
75
|
},
|
|
71
76
|
"scripts": {
|
|
77
|
+
"build": "tsup",
|
|
78
|
+
"dev": "tsup --watch",
|
|
72
79
|
"typecheck": "tsc --noEmit"
|
|
73
80
|
}
|
|
74
81
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
+
import config from "virtual:barodoc/config";
|
|
3
|
+
|
|
2
4
|
interface BreadcrumbItem {
|
|
3
5
|
label: string;
|
|
4
6
|
href?: string;
|
|
@@ -6,15 +8,24 @@ interface BreadcrumbItem {
|
|
|
6
8
|
|
|
7
9
|
interface Props {
|
|
8
10
|
items: BreadcrumbItem[];
|
|
11
|
+
sectionSlug?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { items, sectionSlug = "docs" } = Astro.props;
|
|
15
|
+
|
|
16
|
+
function getSectionLabel(): string {
|
|
17
|
+
if (sectionSlug === "docs") return "Docs";
|
|
18
|
+
const sec = config.sections?.find((s: any) => s.slug === sectionSlug);
|
|
19
|
+
return sec?.label ?? sectionSlug.charAt(0).toUpperCase() + sectionSlug.slice(1);
|
|
9
20
|
}
|
|
10
21
|
|
|
11
|
-
const
|
|
22
|
+
const sectionLabel = getSectionLabel();
|
|
12
23
|
---
|
|
13
24
|
|
|
14
25
|
<nav aria-label="Breadcrumb" class="mb-4">
|
|
15
26
|
<ol class="flex flex-wrap items-center gap-1.5 text-[13px] text-[var(--bd-text-muted)]">
|
|
16
27
|
<li class="flex items-center gap-1.5">
|
|
17
|
-
<a href=
|
|
28
|
+
<a href={`/${sectionSlug}`} class="hover:text-[var(--bd-text)] transition-colors">{sectionLabel}</a>
|
|
18
29
|
</li>
|
|
19
30
|
{items.map((item, i) => (
|
|
20
31
|
<li class="flex items-center gap-1.5">
|
|
@@ -7,11 +7,21 @@ import { getLocalizedNavGroup } from "@barodoc/core";
|
|
|
7
7
|
interface Props {
|
|
8
8
|
currentPath: string;
|
|
9
9
|
currentLocale?: string;
|
|
10
|
+
sectionSlug?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const { currentPath, currentLocale = defaultLocale } = Astro.props;
|
|
13
|
+
const { currentPath, currentLocale = defaultLocale, sectionSlug } = Astro.props;
|
|
14
|
+
|
|
15
|
+
const currentSection = sectionSlug ?? "docs";
|
|
16
|
+
|
|
17
|
+
function getNavForSection() {
|
|
18
|
+
if (currentSection === "docs") return config.navigation;
|
|
19
|
+
const sec = config.sections?.find((s: any) => s.slug === currentSection);
|
|
20
|
+
return sec?.navigation ?? config.navigation;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const sectionNav = getNavForSection();
|
|
13
24
|
|
|
14
|
-
// Normalize path for comparison
|
|
15
25
|
function normalizePath(path: string): string {
|
|
16
26
|
return path.replace(/\/$/, '').replace(/^\//, '');
|
|
17
27
|
}
|
|
@@ -19,19 +29,16 @@ function normalizePath(path: string): string {
|
|
|
19
29
|
function isActive(page: string): boolean {
|
|
20
30
|
const normalized = normalizePath(currentPath);
|
|
21
31
|
const pagePath = normalizePath(page);
|
|
22
|
-
return normalized === pagePath ||
|
|
23
|
-
normalized ===
|
|
24
|
-
normalized === `${currentLocale}/docs/${pagePath}`;
|
|
32
|
+
return normalized === `${currentSection}/${pagePath}` ||
|
|
33
|
+
normalized === `${currentSection}/${currentLocale}/${pagePath}`;
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
function getPageHref(page: string): string {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return `/${currentLocale}/docs/${page}`;
|
|
37
|
+
return currentLocale === defaultLocale
|
|
38
|
+
? `/${currentSection}/${page}`
|
|
39
|
+
: `/${currentSection}/${currentLocale}/${page}`;
|
|
32
40
|
}
|
|
33
41
|
|
|
34
|
-
// Get page title from the page slug
|
|
35
42
|
function getPageTitle(page: string): string {
|
|
36
43
|
const parts = page.split('/');
|
|
37
44
|
const name = parts[parts.length - 1];
|
|
@@ -41,11 +48,10 @@ function getPageTitle(page: string): string {
|
|
|
41
48
|
.join(' ');
|
|
42
49
|
}
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
const groups = config.navigation.map((group) => ({
|
|
51
|
+
const groups = sectionNav.map((group: any) => ({
|
|
46
52
|
title: getLocalizedNavGroup(group, currentLocale, defaultLocale),
|
|
47
53
|
defaultOpen: true,
|
|
48
|
-
items: group.pages.map((page) => ({
|
|
54
|
+
items: group.pages.map((page: string) => ({
|
|
49
55
|
title: getPageTitle(page),
|
|
50
56
|
href: getPageHref(page),
|
|
51
57
|
isActive: isActive(page),
|
|
@@ -7,11 +7,21 @@ import { SidebarWrapper } from "./SidebarWrapper";
|
|
|
7
7
|
interface Props {
|
|
8
8
|
currentPath: string;
|
|
9
9
|
currentLocale?: string;
|
|
10
|
+
sectionSlug?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const { currentPath, currentLocale = defaultLocale } = Astro.props;
|
|
13
|
+
const { currentPath, currentLocale = defaultLocale, sectionSlug } = Astro.props;
|
|
14
|
+
|
|
15
|
+
const currentSection = sectionSlug ?? "docs";
|
|
16
|
+
|
|
17
|
+
function getNavForSection() {
|
|
18
|
+
if (currentSection === "docs") return config.navigation;
|
|
19
|
+
const sec = config.sections?.find((s: any) => s.slug === currentSection);
|
|
20
|
+
return sec?.navigation ?? config.navigation;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const sectionNav = getNavForSection();
|
|
13
24
|
|
|
14
|
-
// Normalize path for comparison
|
|
15
25
|
function normalizePath(path: string): string {
|
|
16
26
|
return path.replace(/\/$/, '').replace(/^\//, '');
|
|
17
27
|
}
|
|
@@ -19,15 +29,16 @@ function normalizePath(path: string): string {
|
|
|
19
29
|
function isActive(page: string): boolean {
|
|
20
30
|
const normalized = normalizePath(currentPath);
|
|
21
31
|
const pagePath = normalizePath(page);
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
return normalized === `${currentSection}/${pagePath}` ||
|
|
33
|
+
normalized === `${currentSection}/${currentLocale}/${pagePath}`;
|
|
24
34
|
}
|
|
25
35
|
|
|
26
36
|
function getPageHref(page: string): string {
|
|
27
|
-
return currentLocale === defaultLocale
|
|
37
|
+
return currentLocale === defaultLocale
|
|
38
|
+
? `/${currentSection}/${page}`
|
|
39
|
+
: `/${currentSection}/${currentLocale}/${page}`;
|
|
28
40
|
}
|
|
29
41
|
|
|
30
|
-
// Get page title from the page slug
|
|
31
42
|
function getPageTitle(page: string): string {
|
|
32
43
|
const parts = page.split('/');
|
|
33
44
|
const name = parts[parts.length - 1];
|
|
@@ -37,11 +48,10 @@ function getPageTitle(page: string): string {
|
|
|
37
48
|
.join(' ');
|
|
38
49
|
}
|
|
39
50
|
|
|
40
|
-
|
|
41
|
-
const groups = config.navigation.map((group) => ({
|
|
51
|
+
const groups = sectionNav.map((group: any) => ({
|
|
42
52
|
title: getLocalizedNavGroup(group, currentLocale, defaultLocale),
|
|
43
53
|
defaultOpen: true,
|
|
44
|
-
items: group.pages.map((page) => ({
|
|
54
|
+
items: group.pages.map((page: string) => ({
|
|
45
55
|
title: getPageTitle(page),
|
|
46
56
|
href: getPageHref(page),
|
|
47
57
|
isActive: isActive(page),
|
|
@@ -34,9 +34,10 @@ interface Props {
|
|
|
34
34
|
breadcrumbs?: BreadcrumbItem[];
|
|
35
35
|
readingTime?: string;
|
|
36
36
|
filePath?: string;
|
|
37
|
+
sectionSlug?: string;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
const { title, description, headings = [], prevPage, nextPage, editUrl, lastUpdated, breadcrumbs = [], readingTime, filePath } = Astro.props;
|
|
40
|
+
const { title, description, headings = [], prevPage, nextPage, editUrl, lastUpdated, breadcrumbs = [], readingTime, filePath, sectionSlug } = Astro.props;
|
|
40
41
|
const currentPath = Astro.url.pathname;
|
|
41
42
|
|
|
42
43
|
// Get locale from path
|
|
@@ -57,14 +58,14 @@ const feedbackEndpoint = config.feedback?.endpoint;
|
|
|
57
58
|
<!-- Desktop Sidebar -->
|
|
58
59
|
<aside class="hidden lg:block w-[240px] shrink-0 border-r border-[var(--bd-border)]">
|
|
59
60
|
<div class="sticky top-14 h-[calc(100vh-3.5rem)] overflow-y-auto overscroll-contain pt-2 pb-8 px-4 sidebar-scroll">
|
|
60
|
-
<Sidebar currentPath={currentPath} currentLocale={currentLocale} />
|
|
61
|
+
<Sidebar currentPath={currentPath} currentLocale={currentLocale} sectionSlug={sectionSlug} />
|
|
61
62
|
</div>
|
|
62
63
|
</aside>
|
|
63
64
|
|
|
64
65
|
<!-- Main Content -->
|
|
65
66
|
<main class="flex-1 min-w-0 max-w-[768px]">
|
|
66
67
|
<div class="px-4 py-8 sm:px-6 sm:py-10 lg:px-10 lg:py-10">
|
|
67
|
-
{breadcrumbs.length > 0 && <Breadcrumb items={breadcrumbs} />}
|
|
68
|
+
{breadcrumbs.length > 0 && <Breadcrumb items={breadcrumbs} sectionSlug={sectionSlug} />}
|
|
68
69
|
{readingTime && (
|
|
69
70
|
<div class="bd-reading-time mb-4">
|
|
70
71
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -174,7 +175,7 @@ const feedbackEndpoint = config.feedback?.endpoint;
|
|
|
174
175
|
</div>
|
|
175
176
|
|
|
176
177
|
<!-- Mobile Navigation -->
|
|
177
|
-
<MobileNav currentPath={currentPath} currentLocale={currentLocale} />
|
|
178
|
+
<MobileNav currentPath={currentPath} currentLocale={currentLocale} sectionSlug={sectionSlug} />
|
|
178
179
|
|
|
179
180
|
<!-- Code copy functionality -->
|
|
180
181
|
<CodeCopy />
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
import BaseLayout from "./BaseLayout.astro";
|
|
3
|
+
import Header from "../components/Header.astro";
|
|
4
|
+
import Banner from "../components/Banner.astro";
|
|
5
|
+
import CodeCopy from "../components/CodeCopy.astro";
|
|
6
|
+
import { defaultLocale } from "virtual:barodoc/i18n";
|
|
7
|
+
import { getLocaleFromPath } from "@barodoc/core";
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
title: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { title, description } = Astro.props;
|
|
15
|
+
const currentPath = Astro.url.pathname;
|
|
16
|
+
const i18nConfig = { defaultLocale, locales: [defaultLocale] };
|
|
17
|
+
const currentLocale = getLocaleFromPath(currentPath, i18nConfig);
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<BaseLayout title={title} description={description}>
|
|
21
|
+
<Banner />
|
|
22
|
+
<Header currentLocale={currentLocale} currentPath={currentPath} />
|
|
23
|
+
|
|
24
|
+
<div class="w-full min-w-0 min-h-[calc(100vh-3.5rem)] flex justify-center">
|
|
25
|
+
<article class="w-full max-w-[720px] px-4 py-10 sm:px-6 lg:px-8">
|
|
26
|
+
<header class="mb-8">
|
|
27
|
+
<h1 class="text-3xl sm:text-4xl font-bold tracking-tight text-[var(--bd-text-heading)] leading-tight">
|
|
28
|
+
{title}
|
|
29
|
+
</h1>
|
|
30
|
+
{description && (
|
|
31
|
+
<p class="mt-3 text-lg text-[var(--bd-text-secondary)] leading-relaxed">
|
|
32
|
+
{description}
|
|
33
|
+
</p>
|
|
34
|
+
)}
|
|
35
|
+
</header>
|
|
36
|
+
|
|
37
|
+
<div class="prose prose-gray dark:prose-invert max-w-none">
|
|
38
|
+
<slot />
|
|
39
|
+
</div>
|
|
40
|
+
<CodeCopy />
|
|
41
|
+
</article>
|
|
42
|
+
</div>
|
|
43
|
+
</BaseLayout>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getCollection, render } from "astro:content";
|
|
3
|
+
import PageLayout from "../layouts/PageLayout.astro";
|
|
4
|
+
import config from "virtual:barodoc/config";
|
|
5
|
+
|
|
6
|
+
export async function getStaticPaths() {
|
|
7
|
+
const reserved = new Set(["blog", "changelog", "docs", "rss.xml"]);
|
|
8
|
+
if (config.sections) {
|
|
9
|
+
for (const s of config.sections as any[]) {
|
|
10
|
+
reserved.add(s.slug);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
let pages: any[] = [];
|
|
14
|
+
try {
|
|
15
|
+
pages = await getCollection("pages" as any);
|
|
16
|
+
} catch {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return pages
|
|
21
|
+
.filter((page) => {
|
|
22
|
+
const slug = page.slug ?? page.id;
|
|
23
|
+
const topLevel = slug.split("/")[0];
|
|
24
|
+
return !reserved.has(topLevel);
|
|
25
|
+
})
|
|
26
|
+
.map((page) => {
|
|
27
|
+
const slug = page.slug ?? page.id;
|
|
28
|
+
return {
|
|
29
|
+
params: { page: slug || undefined },
|
|
30
|
+
props: { page },
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface Props {
|
|
36
|
+
page: any;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { page } = Astro.props;
|
|
40
|
+
const { Content } = await render(page);
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
<PageLayout title={page.data.title} description={page.data.description}>
|
|
44
|
+
<Content />
|
|
45
|
+
</PageLayout>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { getCollection } from "astro:content";
|
|
2
|
+
import { getCollection, render } from "astro:content";
|
|
3
3
|
import BlogLayout from "../../layouts/BlogLayout.astro";
|
|
4
4
|
import readingTime from "reading-time";
|
|
5
5
|
|
|
@@ -12,7 +12,7 @@ export async function getStaticPaths() {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
return posts.map((post) => ({
|
|
15
|
-
params: { slug: post.slug },
|
|
15
|
+
params: { slug: post.slug ?? post.id },
|
|
16
16
|
props: { post },
|
|
17
17
|
}));
|
|
18
18
|
}
|
|
@@ -22,7 +22,7 @@ interface Props {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
const { post } = Astro.props;
|
|
25
|
-
const { Content } = await
|
|
25
|
+
const { Content } = await render(post);
|
|
26
26
|
const readTime = readingTime(post.body ?? "");
|
|
27
27
|
---
|
|
28
28
|
|
|
@@ -42,7 +42,7 @@ const sortedPosts = posts.sort((a, b) => {
|
|
|
42
42
|
<div class="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
|
|
43
43
|
{sortedPosts.map((post) => (
|
|
44
44
|
<a
|
|
45
|
-
href={`/blog/${post.slug}`}
|
|
45
|
+
href={`/blog/${post.slug ?? post.id}`}
|
|
46
46
|
class="group flex flex-col rounded-lg border border-[var(--bd-border)] hover:border-primary-400/50 dark:hover:border-primary-500/40 hover:shadow-[var(--bd-shadow-sm)] transition-all overflow-hidden"
|
|
47
47
|
>
|
|
48
48
|
{post.data.image && (
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { getCollection } from "astro:content";
|
|
2
|
+
import { getCollection, render } from "astro:content";
|
|
3
3
|
import BaseLayout from "../../layouts/BaseLayout.astro";
|
|
4
4
|
import Header from "../../components/Header.astro";
|
|
5
5
|
import Banner from "../../components/Banner.astro";
|
|
@@ -39,7 +39,7 @@ const sorted = entries.sort((a, b) => {
|
|
|
39
39
|
) : (
|
|
40
40
|
<div class="bd-changelog-timeline">
|
|
41
41
|
{sorted.map(async (entry) => {
|
|
42
|
-
const { Content } = await
|
|
42
|
+
const { Content } = await render(entry);
|
|
43
43
|
return (
|
|
44
44
|
<article class="bd-changelog-entry">
|
|
45
45
|
<div class="bd-changelog-marker">
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { getCollection } from "astro:content";
|
|
2
|
+
import { getCollection, render } from "astro:content";
|
|
3
3
|
import DocsLayout from "../../layouts/DocsLayout.astro";
|
|
4
4
|
import config from "virtual:barodoc/config";
|
|
5
5
|
import { defaultLocale, locales } from "virtual:barodoc/i18n";
|
|
@@ -7,46 +7,64 @@ import { getLocalizedNavGroup } from "@barodoc/core";
|
|
|
7
7
|
import readingTime from "reading-time";
|
|
8
8
|
|
|
9
9
|
export async function getStaticPaths() {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
const sections = [
|
|
11
|
+
{ slug: "docs", label: "Documentation", navigation: config.navigation },
|
|
12
|
+
...(config.sections ?? []).map((s: any) => ({
|
|
13
|
+
slug: s.slug,
|
|
14
|
+
label: s.label ?? s.slug,
|
|
15
|
+
navigation: s.navigation,
|
|
16
|
+
})),
|
|
17
|
+
];
|
|
18
|
+
const paths: any[] = [];
|
|
19
|
+
|
|
20
|
+
for (const section of sections) {
|
|
21
|
+
let docs: any[];
|
|
22
|
+
try {
|
|
23
|
+
docs = await getCollection(section.slug as any);
|
|
24
|
+
} catch {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
for (const doc of docs) {
|
|
29
|
+
const docId = doc.slug ?? doc.id;
|
|
30
|
+
const slugParts = docId.split("/");
|
|
31
|
+
const hasLocale = locales.includes(slugParts[0]);
|
|
32
|
+
|
|
33
|
+
let locale = defaultLocale;
|
|
34
|
+
let cleanSlug = docId;
|
|
35
|
+
|
|
36
|
+
if (hasLocale) {
|
|
37
|
+
locale = slugParts[0];
|
|
38
|
+
cleanSlug = slugParts.slice(1).join("/");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const innerPath = locale === defaultLocale
|
|
42
|
+
? cleanSlug
|
|
43
|
+
: `${locale}/${cleanSlug}`;
|
|
44
|
+
|
|
45
|
+
paths.push({
|
|
46
|
+
params: { section: section.slug, slug: innerPath || undefined },
|
|
47
|
+
props: { doc, locale, cleanSlug, sectionSlug: section.slug, sectionNav: section.navigation },
|
|
48
|
+
});
|
|
23
49
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const path = locale === defaultLocale
|
|
27
|
-
? cleanSlug
|
|
28
|
-
: `${locale}/${cleanSlug}`;
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
params: { slug: path || undefined },
|
|
32
|
-
props: { doc, locale, cleanSlug },
|
|
33
|
-
};
|
|
34
|
-
});
|
|
50
|
+
}
|
|
51
|
+
return paths;
|
|
35
52
|
}
|
|
36
53
|
|
|
37
54
|
interface Props {
|
|
38
|
-
doc:
|
|
55
|
+
doc: any;
|
|
39
56
|
locale: string;
|
|
40
57
|
cleanSlug: string;
|
|
58
|
+
sectionSlug: string;
|
|
59
|
+
sectionNav: typeof config.navigation;
|
|
41
60
|
}
|
|
42
61
|
|
|
43
|
-
const { doc, locale, cleanSlug } = Astro.props;
|
|
44
|
-
const { Content, headings } = await
|
|
62
|
+
const { doc, locale, cleanSlug, sectionSlug, sectionNav } = Astro.props;
|
|
63
|
+
const { Content, headings } = await render(doc);
|
|
45
64
|
const readTime = readingTime(doc.body ?? "");
|
|
46
65
|
|
|
47
|
-
// Find the category (navigation group) for this page
|
|
48
66
|
function findCategory(slug: string): string | null {
|
|
49
|
-
for (const group of
|
|
67
|
+
for (const group of sectionNav) {
|
|
50
68
|
if (group.pages.includes(slug)) {
|
|
51
69
|
return getLocalizedNavGroup(group, locale, defaultLocale);
|
|
52
70
|
}
|
|
@@ -54,16 +72,14 @@ function findCategory(slug: string): string | null {
|
|
|
54
72
|
return null;
|
|
55
73
|
}
|
|
56
74
|
|
|
57
|
-
// Get all pages in order from navigation
|
|
58
75
|
function getAllPages(): string[] {
|
|
59
76
|
const pages: string[] = [];
|
|
60
|
-
for (const group of
|
|
77
|
+
for (const group of sectionNav) {
|
|
61
78
|
pages.push(...group.pages);
|
|
62
79
|
}
|
|
63
80
|
return pages;
|
|
64
81
|
}
|
|
65
82
|
|
|
66
|
-
// Get page title from slug
|
|
67
83
|
function getPageTitle(slug: string): string {
|
|
68
84
|
const parts = slug.split('/');
|
|
69
85
|
const name = parts[parts.length - 1];
|
|
@@ -73,32 +89,28 @@ function getPageTitle(slug: string): string {
|
|
|
73
89
|
.join(' ');
|
|
74
90
|
}
|
|
75
91
|
|
|
76
|
-
// Get page href (always /docs/...; non-default locale is inside slug)
|
|
77
92
|
function getPageHref(slug: string): string {
|
|
78
|
-
return
|
|
93
|
+
return `/${sectionSlug}/${locale === defaultLocale ? slug : `${locale}/${slug}`}`;
|
|
79
94
|
}
|
|
80
95
|
|
|
81
|
-
// Find prev/next pages
|
|
82
96
|
const allPages = getAllPages();
|
|
83
97
|
const currentIndex = allPages.indexOf(cleanSlug);
|
|
84
98
|
|
|
85
|
-
const prevPage = currentIndex > 0
|
|
99
|
+
const prevPage = currentIndex > 0
|
|
86
100
|
? { title: getPageTitle(allPages[currentIndex - 1]), href: getPageHref(allPages[currentIndex - 1]) }
|
|
87
101
|
: null;
|
|
88
102
|
|
|
89
|
-
const nextPage = currentIndex < allPages.length - 1
|
|
103
|
+
const nextPage = currentIndex < allPages.length - 1
|
|
90
104
|
? { title: getPageTitle(allPages[currentIndex + 1]), href: getPageHref(allPages[currentIndex + 1]) }
|
|
91
105
|
: null;
|
|
92
106
|
|
|
93
107
|
const category = findCategory(cleanSlug);
|
|
94
108
|
|
|
95
|
-
// Edit link
|
|
96
109
|
const editBaseUrl = config.editLink?.baseUrl;
|
|
97
110
|
const editUrl = editBaseUrl
|
|
98
111
|
? `${editBaseUrl.replace(/\/$/, "")}/${doc.id}`
|
|
99
112
|
: null;
|
|
100
113
|
|
|
101
|
-
// Last updated: use file modification if available
|
|
102
114
|
let lastUpdated: Date | null = null;
|
|
103
115
|
if (config.lastUpdated) {
|
|
104
116
|
const mod = (doc.data as Record<string, unknown>).lastUpdated;
|
|
@@ -107,7 +119,6 @@ if (config.lastUpdated) {
|
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
121
|
|
|
110
|
-
// Breadcrumbs: [Group, Page Title]
|
|
111
122
|
const breadcrumbs: { label: string; href?: string }[] = [];
|
|
112
123
|
if (category) {
|
|
113
124
|
breadcrumbs.push({ label: category });
|
|
@@ -115,8 +126,8 @@ if (category) {
|
|
|
115
126
|
breadcrumbs.push({ label: doc.data.title });
|
|
116
127
|
---
|
|
117
128
|
|
|
118
|
-
<DocsLayout
|
|
119
|
-
title={doc.data.title}
|
|
129
|
+
<DocsLayout
|
|
130
|
+
title={doc.data.title}
|
|
120
131
|
description={doc.data.description}
|
|
121
132
|
headings={headings}
|
|
122
133
|
prevPage={prevPage}
|
|
@@ -125,7 +136,8 @@ breadcrumbs.push({ label: doc.data.title });
|
|
|
125
136
|
lastUpdated={lastUpdated}
|
|
126
137
|
breadcrumbs={breadcrumbs}
|
|
127
138
|
readingTime={readTime.text}
|
|
128
|
-
filePath={`src/content
|
|
139
|
+
filePath={`src/content/${sectionSlug}/${doc.id}`}
|
|
140
|
+
sectionSlug={sectionSlug}
|
|
129
141
|
>
|
|
130
142
|
{category && (
|
|
131
143
|
<p class="text-xs font-semibold uppercase tracking-widest text-primary-600 dark:text-primary-400 mb-3">
|
package/src/theme.ts
CHANGED
|
@@ -76,8 +76,8 @@ function createThemeIntegration(
|
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
injectRoute({
|
|
79
|
-
pattern: "/
|
|
80
|
-
entrypoint: "@barodoc/theme-docs/pages/
|
|
79
|
+
pattern: "/[section]/[...slug]",
|
|
80
|
+
entrypoint: "@barodoc/theme-docs/pages/section/[...slug].astro",
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
if (config?.blog?.enabled !== false) {
|
|
@@ -96,6 +96,11 @@ function createThemeIntegration(
|
|
|
96
96
|
entrypoint: "@barodoc/theme-docs/pages/changelog/index.astro",
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
+
injectRoute({
|
|
100
|
+
pattern: "/[...page]",
|
|
101
|
+
entrypoint: "@barodoc/theme-docs/pages/[...page].astro",
|
|
102
|
+
});
|
|
103
|
+
|
|
99
104
|
updateConfig({
|
|
100
105
|
integrations: [
|
|
101
106
|
mdx({
|