@geenius/docs 0.1.0 → 0.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 +7 -0
- package/README.md +53 -1
- package/package.json +96 -13
- package/packages/convex/dist/index.d.ts +503 -0
- package/packages/convex/dist/index.js +482 -0
- package/packages/convex/dist/index.js.map +1 -0
- package/packages/react/dist/index.d.ts +439 -0
- package/packages/react/dist/index.js +4954 -0
- package/packages/react/dist/index.js.map +1 -0
- package/packages/react-css/{src/styles.css → dist/index.css} +183 -223
- package/packages/react-css/dist/index.css.map +1 -0
- package/packages/react-css/dist/index.d.ts +443 -0
- package/packages/react-css/dist/index.js +5058 -0
- package/packages/react-css/dist/index.js.map +1 -0
- package/packages/shared/dist/index.d.ts +684 -0
- package/packages/shared/dist/index.js +788 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/solidjs/dist/index.d.ts +435 -0
- package/packages/solidjs/dist/index.js +4584 -0
- package/packages/solidjs/dist/index.js.map +1 -0
- package/packages/solidjs-css/{src/styles.css → dist/index.css} +183 -223
- package/packages/solidjs-css/dist/index.css.map +1 -0
- package/packages/solidjs-css/dist/index.d.ts +432 -0
- package/packages/solidjs-css/dist/index.js +4934 -0
- package/packages/solidjs-css/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.nvmrc +0 -1
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -16
- package/CONTRIBUTING.md +0 -26
- package/SECURITY.md +0 -15
- package/SUPPORT.md +0 -8
- package/packages/convex/README.md +0 -1
- package/packages/convex/package.json +0 -12
- package/packages/convex/src/convex.config.ts +0 -3
- package/packages/convex/src/index.ts +0 -3
- package/packages/convex/src/mutations.ts +0 -270
- package/packages/convex/src/queries.ts +0 -175
- package/packages/convex/src/schema.ts +0 -55
- package/packages/react/README.md +0 -1
- package/packages/react/package.json +0 -36
- package/packages/react/src/DocsLayout.tsx +0 -116
- package/packages/react/src/DocsProvider.tsx +0 -93
- package/packages/react/src/RouterDocsContent.tsx +0 -148
- package/packages/react/src/RouterDocsLayout.tsx +0 -161
- package/packages/react/src/components/Breadcrumbs.tsx +0 -34
- package/packages/react/src/components/DocPage.tsx +0 -191
- package/packages/react/src/components/DocSearch.tsx +0 -140
- package/packages/react/src/components/DocSidebar.tsx +0 -86
- package/packages/react/src/components/DocsLayout.tsx +0 -62
- package/packages/react/src/components/EditButton.tsx +0 -26
- package/packages/react/src/components/PageNavigation.tsx +0 -45
- package/packages/react/src/components/TableOfContents.tsx +0 -46
- package/packages/react/src/components/VersionSelector.tsx +0 -60
- package/packages/react/src/components/index.ts +0 -9
- package/packages/react/src/hooks/index.ts +0 -8
- package/packages/react/src/hooks/useDocSearch.ts +0 -55
- package/packages/react/src/hooks/useDocs.ts +0 -57
- package/packages/react/src/hooks/useDocsAdmin.ts +0 -151
- package/packages/react/src/hooks/useTableOfContents.ts +0 -66
- package/packages/react/src/index.ts +0 -38
- package/packages/react/src/pages/DocSearchPage.tsx +0 -129
- package/packages/react/src/pages/DocViewPage.tsx +0 -158
- package/packages/react/src/pages/DocsAdminPage.tsx +0 -330
- package/packages/react/src/pages/DocsIndexPage.tsx +0 -172
- package/packages/react/src/pages/index.ts +0 -4
- package/packages/react/src/useDocs.ts +0 -58
- package/packages/react/tsup.config.ts +0 -12
- package/packages/react-css/README.md +0 -1
- package/packages/react-css/package.json +0 -37
- package/packages/react-css/src/DocsLayout.tsx +0 -117
- package/packages/react-css/src/DocsProvider.tsx +0 -93
- package/packages/react-css/src/RouterDocsContent.tsx +0 -60
- package/packages/react-css/src/RouterDocsLayout.tsx +0 -101
- package/packages/react-css/src/components/DocPage.tsx +0 -21
- package/packages/react-css/src/components/DocSearch.tsx +0 -55
- package/packages/react-css/src/components/DocSidebar.tsx +0 -56
- package/packages/react-css/src/components/DocsLayout.tsx +0 -28
- package/packages/react-css/src/components/common.tsx +0 -93
- package/packages/react-css/src/components/index.ts +0 -5
- package/packages/react-css/src/hooks/index.ts +0 -2
- package/packages/react-css/src/index.ts +0 -6
- package/packages/react-css/src/index.tsx +0 -3
- package/packages/react-css/src/pages/DocViewPage.tsx +0 -78
- package/packages/react-css/src/pages/DocsAdminPage.tsx +0 -101
- package/packages/react-css/src/pages/DocsIndexPage.tsx +0 -68
- package/packages/react-css/src/pages/index.ts +0 -3
- package/packages/react-css/src/useDocs.ts +0 -58
- package/packages/react-css/tsconfig.json +0 -19
- package/packages/react-css/tsup.config.ts +0 -10
- package/packages/shared/README.md +0 -1
- package/packages/shared/package.json +0 -31
- package/packages/shared/src/__tests__/docs.test.ts +0 -69
- package/packages/shared/src/config.ts +0 -80
- package/packages/shared/src/index.ts +0 -179
- package/packages/shared/src/providers/astro.ts +0 -94
- package/packages/shared/src/providers/fumadocs.ts +0 -116
- package/packages/shared/src/providers/internal.ts +0 -80
- package/packages/shared/src/types.ts +0 -73
- package/packages/shared/tsconfig.json +0 -18
- package/packages/shared/tsup.config.ts +0 -12
- package/packages/shared/vitest.config.ts +0 -4
- package/packages/solidjs/README.md +0 -1
- package/packages/solidjs/package.json +0 -33
- package/packages/solidjs/src/DocsLayout.tsx +0 -87
- package/packages/solidjs/src/DocsProvider.tsx +0 -95
- package/packages/solidjs/src/RouterDocsContent.tsx +0 -147
- package/packages/solidjs/src/RouterDocsLayout.tsx +0 -161
- package/packages/solidjs/src/components/Breadcrumbs.tsx +0 -27
- package/packages/solidjs/src/components/DocPage.tsx +0 -110
- package/packages/solidjs/src/components/DocSearch.tsx +0 -81
- package/packages/solidjs/src/components/DocSidebar.tsx +0 -92
- package/packages/solidjs/src/components/DocsLayout.tsx +0 -38
- package/packages/solidjs/src/components/EditButton.tsx +0 -15
- package/packages/solidjs/src/components/PageNavigation.tsx +0 -31
- package/packages/solidjs/src/components/TableOfContents.tsx +0 -41
- package/packages/solidjs/src/components/VersionSelector.tsx +0 -30
- package/packages/solidjs/src/components/index.ts +0 -9
- package/packages/solidjs/src/createDocs.ts +0 -62
- package/packages/solidjs/src/index.ts +0 -28
- package/packages/solidjs/src/pages/DocSearchPage.tsx +0 -72
- package/packages/solidjs/src/pages/DocViewPage.tsx +0 -80
- package/packages/solidjs/src/pages/DocsAdminPage.tsx +0 -123
- package/packages/solidjs/src/pages/DocsIndexPage.tsx +0 -85
- package/packages/solidjs/src/pages/index.ts +0 -4
- package/packages/solidjs/src/primitives/createDocSearch.ts +0 -42
- package/packages/solidjs/src/primitives/createDocs.ts +0 -35
- package/packages/solidjs/src/primitives/createDocsAdmin.ts +0 -63
- package/packages/solidjs/src/primitives/createTableOfContents.ts +0 -51
- package/packages/solidjs/src/primitives/index.ts +0 -4
- package/packages/solidjs/tsup.config.ts +0 -12
- package/packages/solidjs-css/README.md +0 -1
- package/packages/solidjs-css/package.json +0 -36
- package/packages/solidjs-css/src/DocsLayout.tsx +0 -106
- package/packages/solidjs-css/src/DocsProvider.tsx +0 -95
- package/packages/solidjs-css/src/RouterDocsContent.tsx +0 -54
- package/packages/solidjs-css/src/RouterDocsLayout.tsx +0 -104
- package/packages/solidjs-css/src/createDocs.ts +0 -62
- package/packages/solidjs-css/src/index.ts +0 -7
- package/packages/solidjs-css/src/index.tsx +0 -17
- package/packages/solidjs-css/src/pages/DocViewPage.tsx +0 -111
- package/packages/solidjs-css/src/pages/DocsAdminPage.tsx +0 -332
- package/packages/solidjs-css/src/pages/DocsIndexPage.tsx +0 -116
- package/packages/solidjs-css/src/pages/index.ts +0 -3
- package/packages/solidjs-css/src/primitives/index.ts +0 -1
- package/packages/solidjs-css/tsconfig.json +0 -20
- package/packages/solidjs-css/tsup.config.ts +0 -10
- package/pnpm-workspace.yaml +0 -2
|
@@ -0,0 +1,788 @@
|
|
|
1
|
+
import { GeeniusError, ErrorCode } from '@geenius/tools/errors';
|
|
2
|
+
import matter from 'gray-matter';
|
|
3
|
+
|
|
4
|
+
// src/config.ts
|
|
5
|
+
var DocsError = class _DocsError extends GeeniusError {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
super(options);
|
|
8
|
+
this.name = "DocsError";
|
|
9
|
+
Object.setPrototypeOf(this, _DocsError.prototype);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
var DocsConfigurationError = class _DocsConfigurationError extends DocsError {
|
|
13
|
+
constructor(options) {
|
|
14
|
+
super({
|
|
15
|
+
...options,
|
|
16
|
+
code: options.code ?? ErrorCode.INVALID_CONFIG
|
|
17
|
+
});
|
|
18
|
+
this.name = "DocsConfigurationError";
|
|
19
|
+
Object.setPrototypeOf(this, _DocsConfigurationError.prototype);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var DocsProviderError = class _DocsProviderError extends DocsError {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
super({
|
|
25
|
+
...options,
|
|
26
|
+
code: options.code ?? ErrorCode.INTERNAL_ERROR
|
|
27
|
+
});
|
|
28
|
+
this.name = "DocsProviderError";
|
|
29
|
+
Object.setPrototypeOf(this, _DocsProviderError.prototype);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/config.ts
|
|
34
|
+
var _config = null;
|
|
35
|
+
function configureDocs(config) {
|
|
36
|
+
_config = config;
|
|
37
|
+
}
|
|
38
|
+
function getDocsConfig() {
|
|
39
|
+
if (!_config) {
|
|
40
|
+
throw new DocsConfigurationError({
|
|
41
|
+
code: ErrorCode.MISSING_CONFIG,
|
|
42
|
+
message: "Docs not configured. Call configureDocs() first.",
|
|
43
|
+
context: { function: "getDocsConfig" }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return _config;
|
|
47
|
+
}
|
|
48
|
+
function isDocsConfigured() {
|
|
49
|
+
return _config !== null;
|
|
50
|
+
}
|
|
51
|
+
function resetDocsConfig() {
|
|
52
|
+
_config = null;
|
|
53
|
+
}
|
|
54
|
+
function defineDocsConfig(overrides) {
|
|
55
|
+
return {
|
|
56
|
+
baseUrl: "/docs",
|
|
57
|
+
defaultAccess: "public",
|
|
58
|
+
versionsEnabled: false,
|
|
59
|
+
cmdKEnabled: true,
|
|
60
|
+
showReadingTime: true,
|
|
61
|
+
showLastEdited: true,
|
|
62
|
+
printModeEnabled: true,
|
|
63
|
+
...overrides
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function mergeDocsConfig(base, overrides) {
|
|
67
|
+
return {
|
|
68
|
+
...base,
|
|
69
|
+
...overrides
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/utilities.ts
|
|
74
|
+
function toTocLevel(level) {
|
|
75
|
+
if (level === 2 || level === 3 || level === 4) {
|
|
76
|
+
return level;
|
|
77
|
+
}
|
|
78
|
+
return 4;
|
|
79
|
+
}
|
|
80
|
+
function extractToc(mdxContent) {
|
|
81
|
+
const headingRegex = /^(#{2,4})\s+(.+)$/gm;
|
|
82
|
+
const items = [];
|
|
83
|
+
let match = headingRegex.exec(mdxContent);
|
|
84
|
+
while (match !== null) {
|
|
85
|
+
const text = match[2].trim();
|
|
86
|
+
items.push({
|
|
87
|
+
id: slugify(text),
|
|
88
|
+
text,
|
|
89
|
+
level: toTocLevel(match[1].length),
|
|
90
|
+
children: []
|
|
91
|
+
});
|
|
92
|
+
match = headingRegex.exec(mdxContent);
|
|
93
|
+
}
|
|
94
|
+
const nested = [];
|
|
95
|
+
let currentH2 = null;
|
|
96
|
+
let currentH3 = null;
|
|
97
|
+
for (const item of items) {
|
|
98
|
+
if (item.level === 2) {
|
|
99
|
+
currentH2 = item;
|
|
100
|
+
currentH3 = null;
|
|
101
|
+
nested.push(item);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (item.level === 3) {
|
|
105
|
+
currentH3 = item;
|
|
106
|
+
if (currentH2) {
|
|
107
|
+
currentH2.children.push(item);
|
|
108
|
+
} else {
|
|
109
|
+
nested.push(item);
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (currentH3) {
|
|
114
|
+
currentH3.children.push(item);
|
|
115
|
+
} else if (currentH2) {
|
|
116
|
+
currentH2.children.push(item);
|
|
117
|
+
} else {
|
|
118
|
+
nested.push(item);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return nested;
|
|
122
|
+
}
|
|
123
|
+
function calcWordCount(content) {
|
|
124
|
+
const stripped = content.replace(/```[\s\S]*?```/g, "").replace(/`[^`]+`/g, "").replace(/!\[.*?\]\(.*?\)/g, "").replace(/\[([^\]]+)\]\(.*?\)/g, "$1").replace(/[#*_~>|-]/g, "").trim();
|
|
125
|
+
const words = stripped.split(/\s+/).filter(Boolean);
|
|
126
|
+
return {
|
|
127
|
+
wordCount: words.length,
|
|
128
|
+
readingTime: Math.max(1, Math.ceil(words.length / 225))
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function buildBreadcrumbs(sections, sectionId, slug) {
|
|
132
|
+
const crumbs = [{ title: "Docs", href: "/docs" }];
|
|
133
|
+
const sectionMap = new Map(sections.map((section) => [section.id, section]));
|
|
134
|
+
const trail = [];
|
|
135
|
+
let current = sectionMap.get(sectionId);
|
|
136
|
+
while (current) {
|
|
137
|
+
trail.unshift(current);
|
|
138
|
+
current = current.parentId ? sectionMap.get(current.parentId) : void 0;
|
|
139
|
+
}
|
|
140
|
+
for (const section of trail) {
|
|
141
|
+
crumbs.push({ title: section.title, href: `/docs/${section.slug}` });
|
|
142
|
+
}
|
|
143
|
+
if (slug) {
|
|
144
|
+
const parentSlug = trail[trail.length - 1]?.slug ?? "";
|
|
145
|
+
crumbs.push({ title: slug, href: `/docs/${parentSlug}/${slug}` });
|
|
146
|
+
}
|
|
147
|
+
return crumbs;
|
|
148
|
+
}
|
|
149
|
+
function buildDocsIndex(pages, sections) {
|
|
150
|
+
const sectionMap = new Map(sections.map((section) => [section.id, section]));
|
|
151
|
+
return pages.filter((page) => page.status === "published").map((page) => {
|
|
152
|
+
const section = sectionMap.get(page.sectionId);
|
|
153
|
+
return {
|
|
154
|
+
pageId: page.id,
|
|
155
|
+
pageTitle: page.title,
|
|
156
|
+
sectionTitle: section?.title ?? "",
|
|
157
|
+
sectionSlug: section?.slug ?? "",
|
|
158
|
+
slug: page.slug,
|
|
159
|
+
highlight: page.excerpt ?? page.content.slice(0, 160),
|
|
160
|
+
score: 0,
|
|
161
|
+
tags: page.tags
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
function searchDocs(query, index) {
|
|
166
|
+
if (!query.trim()) {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
170
|
+
return index.map((entry) => {
|
|
171
|
+
let score = 0;
|
|
172
|
+
const titleLower = entry.pageTitle.toLowerCase();
|
|
173
|
+
const highlightLower = entry.highlight.toLowerCase();
|
|
174
|
+
const sectionLower = entry.sectionTitle.toLowerCase();
|
|
175
|
+
const tagsLower = entry.tags.map((tag) => tag.toLowerCase());
|
|
176
|
+
for (const term of terms) {
|
|
177
|
+
if (titleLower.includes(term)) {
|
|
178
|
+
score += 10;
|
|
179
|
+
}
|
|
180
|
+
if (tagsLower.some((tag) => tag.includes(term))) {
|
|
181
|
+
score += 5;
|
|
182
|
+
}
|
|
183
|
+
if (sectionLower.includes(term)) {
|
|
184
|
+
score += 3;
|
|
185
|
+
}
|
|
186
|
+
if (highlightLower.includes(term)) {
|
|
187
|
+
score += 2;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return { ...entry, score };
|
|
191
|
+
}).filter((entry) => entry.score > 0).sort((left, right) => right.score - left.score).slice(0, 20);
|
|
192
|
+
}
|
|
193
|
+
function slugify(title) {
|
|
194
|
+
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
195
|
+
}
|
|
196
|
+
function highlightMatch(text, query, maxLen = 160) {
|
|
197
|
+
if (!query.trim()) {
|
|
198
|
+
return text.slice(0, maxLen);
|
|
199
|
+
}
|
|
200
|
+
const lowerText = text.toLowerCase();
|
|
201
|
+
const lowerQuery = query.toLowerCase();
|
|
202
|
+
const index = lowerText.indexOf(lowerQuery);
|
|
203
|
+
if (index === -1) {
|
|
204
|
+
return text.slice(0, maxLen);
|
|
205
|
+
}
|
|
206
|
+
const start = Math.max(0, index - 40);
|
|
207
|
+
const end = Math.min(text.length, index + query.length + (maxLen - 80));
|
|
208
|
+
let snippet = text.slice(start, end);
|
|
209
|
+
if (start > 0) {
|
|
210
|
+
snippet = `\u2026${snippet}`;
|
|
211
|
+
}
|
|
212
|
+
if (end < text.length) {
|
|
213
|
+
snippet = `${snippet}\u2026`;
|
|
214
|
+
}
|
|
215
|
+
return snippet;
|
|
216
|
+
}
|
|
217
|
+
var defaultDocsConfig = {
|
|
218
|
+
siteName: "Docs",
|
|
219
|
+
cmdKEnabled: true,
|
|
220
|
+
showReadingTime: true,
|
|
221
|
+
showLastEdited: true,
|
|
222
|
+
versionsEnabled: false,
|
|
223
|
+
defaultAccess: "public",
|
|
224
|
+
printModeEnabled: true
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// src/providers/astro.ts
|
|
228
|
+
function sectionTitle(sectionId) {
|
|
229
|
+
return sectionId.split(/[-_/]/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || "General";
|
|
230
|
+
}
|
|
231
|
+
function asString(value) {
|
|
232
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
233
|
+
}
|
|
234
|
+
function asNumber(value) {
|
|
235
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
if (typeof value === "string") {
|
|
239
|
+
const parsed = Number.parseInt(value, 10);
|
|
240
|
+
if (Number.isFinite(parsed)) {
|
|
241
|
+
return parsed;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return 0;
|
|
245
|
+
}
|
|
246
|
+
function asAccess(value) {
|
|
247
|
+
if (value === "team" || value === "admin") {
|
|
248
|
+
return value;
|
|
249
|
+
}
|
|
250
|
+
return "public";
|
|
251
|
+
}
|
|
252
|
+
function asStatus(value) {
|
|
253
|
+
if (value === "draft" || value === "archived") {
|
|
254
|
+
return value;
|
|
255
|
+
}
|
|
256
|
+
return "published";
|
|
257
|
+
}
|
|
258
|
+
function asTags(value) {
|
|
259
|
+
if (Array.isArray(value)) {
|
|
260
|
+
return value.filter((entry) => typeof entry === "string");
|
|
261
|
+
}
|
|
262
|
+
if (typeof value === "string") {
|
|
263
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
264
|
+
}
|
|
265
|
+
return [];
|
|
266
|
+
}
|
|
267
|
+
function createSidebar(pages) {
|
|
268
|
+
const sections = /* @__PURE__ */ new Map();
|
|
269
|
+
for (const page of pages.filter((entry) => entry.status === "published")) {
|
|
270
|
+
const title = sectionTitle(page.sectionId);
|
|
271
|
+
const existing = sections.get(page.sectionId) ?? {
|
|
272
|
+
id: page.sectionId,
|
|
273
|
+
title,
|
|
274
|
+
slug: slugify(title),
|
|
275
|
+
pages: []
|
|
276
|
+
};
|
|
277
|
+
existing.pages.push({ slug: page.slug, title: page.title });
|
|
278
|
+
sections.set(page.sectionId, existing);
|
|
279
|
+
}
|
|
280
|
+
return [...sections.values()];
|
|
281
|
+
}
|
|
282
|
+
var AstroDocsProvider = class {
|
|
283
|
+
pages = [];
|
|
284
|
+
/**
|
|
285
|
+
* Loads docs from an Astro-style `import.meta.glob()` result.
|
|
286
|
+
*
|
|
287
|
+
* @param globResult - Lazy or eager Astro content loaders keyed by path.
|
|
288
|
+
* @returns Nothing. The provider page set is replaced in memory.
|
|
289
|
+
*/
|
|
290
|
+
async loadFromGlob(globResult) {
|
|
291
|
+
const parsed = await Promise.all(
|
|
292
|
+
Object.entries(globResult).map(async ([path, loader]) => {
|
|
293
|
+
const raw = typeof loader === "function" ? await loader() : loader;
|
|
294
|
+
return this.parseDoc(path, raw);
|
|
295
|
+
})
|
|
296
|
+
);
|
|
297
|
+
this.pages = this.linkPages(parsed);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Loads docs from already-read file contents.
|
|
301
|
+
*
|
|
302
|
+
* @param files - File path and content pairs to normalise.
|
|
303
|
+
* @returns Nothing. The provider page set is replaced in memory.
|
|
304
|
+
*/
|
|
305
|
+
async loadFromFiles(files) {
|
|
306
|
+
this.pages = this.linkPages(
|
|
307
|
+
files.map((file) => this.parseDoc(file.path, file.content))
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
parseDoc(path, raw) {
|
|
311
|
+
const parsed = matter(raw);
|
|
312
|
+
const pathParts = path.replace(/.*content\/docs\//, "").replace(/\.(mdx?|md)$/, "").split("/").filter(Boolean);
|
|
313
|
+
const slug = pathParts.join("/");
|
|
314
|
+
const sectionId = pathParts[0] ?? "general";
|
|
315
|
+
const titleFromPath = pathParts[pathParts.length - 1] ?? slug;
|
|
316
|
+
const { wordCount, readingTime } = calcWordCount(parsed.content);
|
|
317
|
+
const authorName = asString(parsed.data.author) ?? "Geenius";
|
|
318
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
319
|
+
const status = parsed.data.draft === true ? "draft" : asStatus(parsed.data.status);
|
|
320
|
+
return {
|
|
321
|
+
id: asString(parsed.data.id) ?? slug,
|
|
322
|
+
title: asString(parsed.data.title) ?? sectionTitle(titleFromPath),
|
|
323
|
+
slug,
|
|
324
|
+
content: parsed.content,
|
|
325
|
+
excerpt: asString(parsed.data.description),
|
|
326
|
+
sectionId,
|
|
327
|
+
order: asNumber(parsed.data.order),
|
|
328
|
+
author: {
|
|
329
|
+
name: authorName,
|
|
330
|
+
avatar: asString(parsed.data.avatar)
|
|
331
|
+
},
|
|
332
|
+
lastEditedBy: asString(parsed.data.lastEditedBy) ? {
|
|
333
|
+
name: asString(parsed.data.lastEditedBy) ?? authorName,
|
|
334
|
+
editedAt: asString(parsed.data.lastEditedAt) ?? now
|
|
335
|
+
} : void 0,
|
|
336
|
+
version: asString(parsed.data.version),
|
|
337
|
+
access: asAccess(parsed.data.access),
|
|
338
|
+
tags: asTags(parsed.data.tags),
|
|
339
|
+
status,
|
|
340
|
+
createdAt: asString(parsed.data.createdAt) ?? now,
|
|
341
|
+
updatedAt: asString(parsed.data.updatedAt) ?? now,
|
|
342
|
+
wordCount,
|
|
343
|
+
readingTime,
|
|
344
|
+
viewCount: asNumber(parsed.data.viewCount)
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
linkPages(pages) {
|
|
348
|
+
const sorted = [...pages].sort((left, right) => left.order - right.order);
|
|
349
|
+
return sorted.map((page, index) => {
|
|
350
|
+
const prev = sorted[index - 1];
|
|
351
|
+
const next = sorted[index + 1];
|
|
352
|
+
const prevLink = prev ? { slug: prev.slug, title: prev.title } : null;
|
|
353
|
+
const nextLink = next ? { slug: next.slug, title: next.title } : null;
|
|
354
|
+
return {
|
|
355
|
+
...page,
|
|
356
|
+
prev: prevLink,
|
|
357
|
+
next: nextLink,
|
|
358
|
+
toc: extractToc(page.content)
|
|
359
|
+
};
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Loads the sidebar structure derived from the parsed Astro pages.
|
|
364
|
+
*
|
|
365
|
+
* @returns Sidebar navigation entries derived from the published pages.
|
|
366
|
+
*/
|
|
367
|
+
async getSidebar() {
|
|
368
|
+
return createSidebar(this.pages);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Resolves a linked docs page by slug.
|
|
372
|
+
*
|
|
373
|
+
* @param slug - Target page slug.
|
|
374
|
+
* @returns The linked page or `null` when no page matches the slug.
|
|
375
|
+
*/
|
|
376
|
+
async getPage(slug) {
|
|
377
|
+
return this.pages.find((page) => page.slug === slug) ?? null;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* Returns all published pages managed by the provider.
|
|
381
|
+
*
|
|
382
|
+
* @returns Published pages in their linked navigation order.
|
|
383
|
+
*/
|
|
384
|
+
async getAllPages() {
|
|
385
|
+
return this.pages.filter((page) => page.status === "published");
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Searches the parsed Astro page set.
|
|
389
|
+
*
|
|
390
|
+
* @param query - User-entered search query.
|
|
391
|
+
* @returns Ranked search results derived from the published pages.
|
|
392
|
+
*/
|
|
393
|
+
async search(query) {
|
|
394
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
395
|
+
if (!normalizedQuery) {
|
|
396
|
+
return [];
|
|
397
|
+
}
|
|
398
|
+
return this.pages.filter((page) => page.status === "published").map((page) => {
|
|
399
|
+
let score = 0;
|
|
400
|
+
if (page.title.toLowerCase().includes(normalizedQuery)) {
|
|
401
|
+
score += 10;
|
|
402
|
+
}
|
|
403
|
+
if (page.tags.some((tag) => tag.toLowerCase().includes(normalizedQuery))) {
|
|
404
|
+
score += 4;
|
|
405
|
+
}
|
|
406
|
+
if (page.content.toLowerCase().includes(normalizedQuery)) {
|
|
407
|
+
score += 2;
|
|
408
|
+
}
|
|
409
|
+
if (score === 0) {
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
return {
|
|
413
|
+
pageId: page.id,
|
|
414
|
+
pageTitle: page.title,
|
|
415
|
+
sectionTitle: sectionTitle(page.sectionId),
|
|
416
|
+
slug: page.slug,
|
|
417
|
+
highlight: highlightMatch(page.excerpt ?? page.content, query),
|
|
418
|
+
score
|
|
419
|
+
};
|
|
420
|
+
}).filter((result) => result !== null).sort((left, right) => right.score - left.score);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Resolves previous and next pages for a slug.
|
|
424
|
+
*
|
|
425
|
+
* @param slug - Target page slug.
|
|
426
|
+
* @returns Linked previous and next page records when available.
|
|
427
|
+
*/
|
|
428
|
+
async getNavigation(slug) {
|
|
429
|
+
const page = this.pages.find((entry) => entry.slug === slug);
|
|
430
|
+
if (!page) {
|
|
431
|
+
return { prev: null, next: null };
|
|
432
|
+
}
|
|
433
|
+
return {
|
|
434
|
+
prev: page.prev ? this.pages.find((entry) => entry.slug === page.prev?.slug) ?? null : null,
|
|
435
|
+
next: page.next ? this.pages.find((entry) => entry.slug === page.next?.slug) ?? null : null
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
// src/providers/fumadocs.ts
|
|
441
|
+
function sectionTitle2(sectionId) {
|
|
442
|
+
return sectionId.split(/[-_/]/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || "General";
|
|
443
|
+
}
|
|
444
|
+
function asString2(value) {
|
|
445
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
446
|
+
}
|
|
447
|
+
function asAccess2(value) {
|
|
448
|
+
if (value === "team" || value === "admin") {
|
|
449
|
+
return value;
|
|
450
|
+
}
|
|
451
|
+
return "public";
|
|
452
|
+
}
|
|
453
|
+
function asStatus2(value) {
|
|
454
|
+
if (value === "draft" || value === "archived") {
|
|
455
|
+
return value;
|
|
456
|
+
}
|
|
457
|
+
return "published";
|
|
458
|
+
}
|
|
459
|
+
function asTags2(value) {
|
|
460
|
+
if (Array.isArray(value)) {
|
|
461
|
+
return value.filter((entry) => typeof entry === "string");
|
|
462
|
+
}
|
|
463
|
+
if (typeof value === "string") {
|
|
464
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
465
|
+
}
|
|
466
|
+
return [];
|
|
467
|
+
}
|
|
468
|
+
function createSidebar2(pages) {
|
|
469
|
+
const sections = /* @__PURE__ */ new Map();
|
|
470
|
+
for (const page of pages.filter((entry) => entry.status === "published")) {
|
|
471
|
+
const title = sectionTitle2(page.sectionId);
|
|
472
|
+
const existing = sections.get(page.sectionId) ?? {
|
|
473
|
+
id: page.sectionId,
|
|
474
|
+
title,
|
|
475
|
+
slug: slugify(title),
|
|
476
|
+
pages: []
|
|
477
|
+
};
|
|
478
|
+
existing.pages.push({ slug: page.slug, title: page.title });
|
|
479
|
+
sections.set(page.sectionId, existing);
|
|
480
|
+
}
|
|
481
|
+
return [...sections.values()];
|
|
482
|
+
}
|
|
483
|
+
var FumadocsDocsProvider = class {
|
|
484
|
+
pages = [];
|
|
485
|
+
tree = [];
|
|
486
|
+
/**
|
|
487
|
+
* Loads pages and an optional page tree from Fumadocs.
|
|
488
|
+
*
|
|
489
|
+
* @param pages - Source pages supplied by Fumadocs.
|
|
490
|
+
* @param tree - Optional source page tree for nested sidebar rendering.
|
|
491
|
+
* @returns Nothing. The provider page set is replaced in memory.
|
|
492
|
+
*/
|
|
493
|
+
loadFromSource(pages, tree = []) {
|
|
494
|
+
this.tree = tree;
|
|
495
|
+
this.pages = this.linkPages(pages.map((page) => this.normalizePage(page)));
|
|
496
|
+
}
|
|
497
|
+
normalizePage(page) {
|
|
498
|
+
const slugParts = page.slugs ?? page.slug?.split("/") ?? [];
|
|
499
|
+
const slug = slugParts.join("/");
|
|
500
|
+
const sectionId = slugParts[0] ?? "general";
|
|
501
|
+
const title = page.data.title ?? slugParts[slugParts.length - 1] ?? slug;
|
|
502
|
+
const content = page.data.body ?? "";
|
|
503
|
+
const { wordCount, readingTime } = calcWordCount(content);
|
|
504
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
505
|
+
return {
|
|
506
|
+
id: slug,
|
|
507
|
+
title,
|
|
508
|
+
slug,
|
|
509
|
+
content,
|
|
510
|
+
excerpt: page.data.description,
|
|
511
|
+
sectionId,
|
|
512
|
+
order: page.data.order ?? 0,
|
|
513
|
+
author: {
|
|
514
|
+
name: page.data.author ?? "Geenius",
|
|
515
|
+
avatar: asString2(page.data.avatar)
|
|
516
|
+
},
|
|
517
|
+
lastEditedBy: asString2(page.data.lastModified ?? page.data.lastUpdated) ? {
|
|
518
|
+
name: page.data.author ?? "Geenius",
|
|
519
|
+
editedAt: asString2(page.data.lastModified ?? page.data.lastUpdated) ?? now
|
|
520
|
+
} : void 0,
|
|
521
|
+
version: asString2(page.data.version),
|
|
522
|
+
access: asAccess2(page.data.access),
|
|
523
|
+
tags: asTags2(page.data.tags),
|
|
524
|
+
status: page.data.draft === true ? "draft" : asStatus2(page.data.status),
|
|
525
|
+
createdAt: now,
|
|
526
|
+
updatedAt: asString2(page.data.lastModified ?? page.data.lastUpdated) ?? now,
|
|
527
|
+
wordCount,
|
|
528
|
+
readingTime,
|
|
529
|
+
viewCount: 0,
|
|
530
|
+
toc: page.data.toc ?? extractToc(content)
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
linkPages(pages) {
|
|
534
|
+
const sorted = [...pages].sort((left, right) => left.order - right.order);
|
|
535
|
+
return sorted.map((page, index) => {
|
|
536
|
+
const prev = sorted[index - 1];
|
|
537
|
+
const next = sorted[index + 1];
|
|
538
|
+
const prevLink = prev ? { slug: prev.slug, title: prev.title } : null;
|
|
539
|
+
const nextLink = next ? { slug: next.slug, title: next.title } : null;
|
|
540
|
+
return {
|
|
541
|
+
...page,
|
|
542
|
+
prev: prevLink,
|
|
543
|
+
next: nextLink
|
|
544
|
+
};
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
treeToSidebar(nodes) {
|
|
548
|
+
return nodes.filter((node) => node.type === "folder").map((folder) => {
|
|
549
|
+
const title = folder.name ?? "Section";
|
|
550
|
+
const children = folder.children ?? [];
|
|
551
|
+
const pages = children.filter((child) => child.type === "page").map((child) => ({
|
|
552
|
+
slug: child.slug ?? "",
|
|
553
|
+
title: child.name ?? child.slug ?? "Untitled"
|
|
554
|
+
}));
|
|
555
|
+
const nestedChildren = this.treeToSidebar(
|
|
556
|
+
children.filter((child) => child.type === "folder")
|
|
557
|
+
);
|
|
558
|
+
return {
|
|
559
|
+
id: folder.slug ?? slugify(title),
|
|
560
|
+
title,
|
|
561
|
+
slug: folder.slug ?? slugify(title),
|
|
562
|
+
icon: folder.icon,
|
|
563
|
+
pages,
|
|
564
|
+
children: nestedChildren.length > 0 ? nestedChildren : void 0
|
|
565
|
+
};
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Loads the sidebar structure derived from the Fumadocs tree or grouped pages.
|
|
570
|
+
*
|
|
571
|
+
* @returns Sidebar navigation entries derived from the published pages.
|
|
572
|
+
*/
|
|
573
|
+
async getSidebar() {
|
|
574
|
+
if (this.tree.length > 0) {
|
|
575
|
+
return this.treeToSidebar(this.tree);
|
|
576
|
+
}
|
|
577
|
+
return createSidebar2(this.pages);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Resolves a linked docs page by slug.
|
|
581
|
+
*
|
|
582
|
+
* @param slug - Target page slug.
|
|
583
|
+
* @returns The linked page or `null` when no page matches the slug.
|
|
584
|
+
*/
|
|
585
|
+
async getPage(slug) {
|
|
586
|
+
return this.pages.find((page) => page.slug === slug) ?? null;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Returns all published pages managed by the provider.
|
|
590
|
+
*
|
|
591
|
+
* @returns Published pages in their linked navigation order.
|
|
592
|
+
*/
|
|
593
|
+
async getAllPages() {
|
|
594
|
+
return this.pages.filter((page) => page.status === "published");
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Searches the provider-backed page set.
|
|
598
|
+
*
|
|
599
|
+
* @param query - User-entered search query.
|
|
600
|
+
* @returns Ranked search results derived from the published pages.
|
|
601
|
+
*/
|
|
602
|
+
async search(query) {
|
|
603
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
604
|
+
if (!normalizedQuery) {
|
|
605
|
+
return [];
|
|
606
|
+
}
|
|
607
|
+
return this.pages.filter((page) => page.status === "published").map((page) => {
|
|
608
|
+
let score = 0;
|
|
609
|
+
if (page.title.toLowerCase().includes(normalizedQuery)) {
|
|
610
|
+
score += 10;
|
|
611
|
+
}
|
|
612
|
+
if (page.tags.some((tag) => tag.toLowerCase().includes(normalizedQuery))) {
|
|
613
|
+
score += 4;
|
|
614
|
+
}
|
|
615
|
+
if (page.content.toLowerCase().includes(normalizedQuery)) {
|
|
616
|
+
score += 2;
|
|
617
|
+
}
|
|
618
|
+
if (page.excerpt?.toLowerCase().includes(normalizedQuery)) {
|
|
619
|
+
score += 1;
|
|
620
|
+
}
|
|
621
|
+
if (score === 0) {
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
pageId: page.id,
|
|
626
|
+
pageTitle: page.title,
|
|
627
|
+
sectionTitle: sectionTitle2(page.sectionId),
|
|
628
|
+
slug: page.slug,
|
|
629
|
+
highlight: highlightMatch(page.excerpt ?? page.content, query),
|
|
630
|
+
score
|
|
631
|
+
};
|
|
632
|
+
}).filter((result) => result !== null).sort((left, right) => right.score - left.score);
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Resolves previous and next pages for a slug.
|
|
636
|
+
*
|
|
637
|
+
* @param slug - Target page slug.
|
|
638
|
+
* @returns Linked previous and next page records when available.
|
|
639
|
+
*/
|
|
640
|
+
async getNavigation(slug) {
|
|
641
|
+
const page = this.pages.find((entry) => entry.slug === slug);
|
|
642
|
+
if (!page) {
|
|
643
|
+
return { prev: null, next: null };
|
|
644
|
+
}
|
|
645
|
+
return {
|
|
646
|
+
prev: page.prev ? this.pages.find((entry) => entry.slug === page.prev?.slug) ?? null : null,
|
|
647
|
+
next: page.next ? this.pages.find((entry) => entry.slug === page.next?.slug) ?? null : null
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
// src/providers/internal.ts
|
|
653
|
+
function sectionTitle3(sectionId) {
|
|
654
|
+
return sectionId.split(/[-_/]/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || "General";
|
|
655
|
+
}
|
|
656
|
+
function createSidebar3(pages) {
|
|
657
|
+
const sections = /* @__PURE__ */ new Map();
|
|
658
|
+
for (const page of pages.filter((entry) => entry.status === "published")) {
|
|
659
|
+
const title = sectionTitle3(page.sectionId);
|
|
660
|
+
const entry = sections.get(page.sectionId) ?? {
|
|
661
|
+
id: page.sectionId,
|
|
662
|
+
title,
|
|
663
|
+
slug: slugify(title),
|
|
664
|
+
pages: []
|
|
665
|
+
};
|
|
666
|
+
entry.pages.push({ slug: page.slug, title: page.title });
|
|
667
|
+
sections.set(page.sectionId, entry);
|
|
668
|
+
}
|
|
669
|
+
return [...sections.values()].map((entry) => ({
|
|
670
|
+
...entry,
|
|
671
|
+
pages: [...entry.pages].sort(
|
|
672
|
+
(left, right) => left.title.localeCompare(right.title)
|
|
673
|
+
)
|
|
674
|
+
}));
|
|
675
|
+
}
|
|
676
|
+
var InternalDocsProvider = class {
|
|
677
|
+
pages = [];
|
|
678
|
+
/**
|
|
679
|
+
* @param pages - Optional initial page records to seed the provider with.
|
|
680
|
+
*/
|
|
681
|
+
constructor(pages = []) {
|
|
682
|
+
this.pages = this.linkPages(pages);
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Replaces the provider's page set.
|
|
686
|
+
*
|
|
687
|
+
* @param pages - Fresh page records to seed into the provider.
|
|
688
|
+
* @returns Nothing. The provider page set is replaced in memory.
|
|
689
|
+
*/
|
|
690
|
+
setPages(pages) {
|
|
691
|
+
this.pages = this.linkPages(pages);
|
|
692
|
+
}
|
|
693
|
+
linkPages(pages) {
|
|
694
|
+
const sorted = [...pages].sort((left, right) => left.order - right.order);
|
|
695
|
+
return sorted.map((page, index) => {
|
|
696
|
+
const prev = sorted[index - 1];
|
|
697
|
+
const next = sorted[index + 1];
|
|
698
|
+
const prevLink = prev ? { slug: prev.slug, title: prev.title } : null;
|
|
699
|
+
const nextLink = next ? { slug: next.slug, title: next.title } : null;
|
|
700
|
+
return {
|
|
701
|
+
...page,
|
|
702
|
+
prev: prevLink,
|
|
703
|
+
next: nextLink,
|
|
704
|
+
toc: extractToc(page.content)
|
|
705
|
+
};
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Loads the sidebar structure derived from the current page set.
|
|
710
|
+
*
|
|
711
|
+
* @returns Sidebar navigation entries derived from the published pages.
|
|
712
|
+
*/
|
|
713
|
+
async getSidebar() {
|
|
714
|
+
return createSidebar3(this.pages);
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Resolves a linked docs page by slug.
|
|
718
|
+
*
|
|
719
|
+
* @param slug - Target page slug.
|
|
720
|
+
* @returns The linked page or `null` when no page matches the slug.
|
|
721
|
+
*/
|
|
722
|
+
async getPage(slug) {
|
|
723
|
+
return this.pages.find((page) => page.slug === slug) ?? null;
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Returns all published pages managed by the provider.
|
|
727
|
+
*
|
|
728
|
+
* @returns Published pages in their linked navigation order.
|
|
729
|
+
*/
|
|
730
|
+
async getAllPages() {
|
|
731
|
+
return this.pages.filter((page) => page.status === "published");
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Searches the provider-backed page set.
|
|
735
|
+
*
|
|
736
|
+
* @param query - User-entered search query.
|
|
737
|
+
* @returns Ranked search results derived from the published pages.
|
|
738
|
+
*/
|
|
739
|
+
async search(query) {
|
|
740
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
741
|
+
if (!normalizedQuery) {
|
|
742
|
+
return [];
|
|
743
|
+
}
|
|
744
|
+
return this.pages.filter((page) => page.status === "published").map((page) => {
|
|
745
|
+
let score = 0;
|
|
746
|
+
if (page.title.toLowerCase().includes(normalizedQuery)) {
|
|
747
|
+
score += 10;
|
|
748
|
+
}
|
|
749
|
+
if (page.tags.some((tag) => tag.toLowerCase().includes(normalizedQuery))) {
|
|
750
|
+
score += 4;
|
|
751
|
+
}
|
|
752
|
+
if (page.content.toLowerCase().includes(normalizedQuery)) {
|
|
753
|
+
score += 2;
|
|
754
|
+
}
|
|
755
|
+
if (score === 0) {
|
|
756
|
+
return null;
|
|
757
|
+
}
|
|
758
|
+
return {
|
|
759
|
+
pageId: page.id,
|
|
760
|
+
pageTitle: page.title,
|
|
761
|
+
sectionTitle: sectionTitle3(page.sectionId),
|
|
762
|
+
slug: page.slug,
|
|
763
|
+
highlight: highlightMatch(page.excerpt ?? page.content, query),
|
|
764
|
+
score
|
|
765
|
+
};
|
|
766
|
+
}).filter((result) => result !== null).sort((left, right) => right.score - left.score);
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Resolves previous and next pages for a slug.
|
|
770
|
+
*
|
|
771
|
+
* @param slug - Target page slug.
|
|
772
|
+
* @returns Linked previous and next page records when available.
|
|
773
|
+
*/
|
|
774
|
+
async getNavigation(slug) {
|
|
775
|
+
const page = this.pages.find((entry) => entry.slug === slug);
|
|
776
|
+
if (!page) {
|
|
777
|
+
return { prev: null, next: null };
|
|
778
|
+
}
|
|
779
|
+
return {
|
|
780
|
+
prev: page.prev ? this.pages.find((entry) => entry.slug === page.prev?.slug) ?? null : null,
|
|
781
|
+
next: page.next ? this.pages.find((entry) => entry.slug === page.next?.slug) ?? null : null
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
export { AstroDocsProvider, DocsConfigurationError, DocsError, DocsProviderError, FumadocsDocsProvider, InternalDocsProvider, buildBreadcrumbs, buildDocsIndex, calcWordCount, configureDocs, defaultDocsConfig, defineDocsConfig, extractToc, getDocsConfig, highlightMatch, isDocsConfigured, mergeDocsConfig, resetDocsConfig, searchDocs, slugify };
|
|
787
|
+
//# sourceMappingURL=index.js.map
|
|
788
|
+
//# sourceMappingURL=index.js.map
|