@lexibase/rdx-next 4.2.0 → 5.0.1
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/bin/locale-routes.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { lstat, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
|
|
1
|
+
import { lstat, mkdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
|
|
4
4
|
const defaultFiles = [
|
|
@@ -14,6 +14,7 @@ const generated = [
|
|
|
14
14
|
'app/(rdx-locales)/[locale]/not-found.tsx',
|
|
15
15
|
'app/(rdx-locales)/[locale]/docs/[[...slug]]/page.tsx',
|
|
16
16
|
'app/(rdx-locales)/[locale]/rdx-search/[source]/route.ts',
|
|
17
|
+
'app/(rdx-locales)/[locale]/docs/llms.txt/route.ts',
|
|
17
18
|
]
|
|
18
19
|
|
|
19
20
|
/** Root layouts keep HTML language correct on the server, without middleware. */
|
|
@@ -34,6 +35,18 @@ export async function prepareLocaleRoutes(project, runtime, template) {
|
|
|
34
35
|
}
|
|
35
36
|
return current
|
|
36
37
|
}
|
|
38
|
+
// An existing public index owns this URL. Keep it when upgrading a project.
|
|
39
|
+
const publicIndex = path.join(project.rootDir, 'public', 'docs', 'llms.txt')
|
|
40
|
+
const hasPublicIndex = await stat(publicIndex).then(
|
|
41
|
+
(entry) => entry.isFile(),
|
|
42
|
+
(error) => {
|
|
43
|
+
if (error.code === 'ENOENT' || error.code === 'ENOTDIR') return false
|
|
44
|
+
throw error
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
if (hasPublicIndex)
|
|
48
|
+
await rm(await safe('app/docs/llms.txt/route.ts'), { force: true })
|
|
49
|
+
|
|
37
50
|
const marker = await safe('.rdx-localization.json')
|
|
38
51
|
let owned = false
|
|
39
52
|
try {
|
|
@@ -130,6 +143,23 @@ export async function generateStaticParams() {
|
|
|
130
143
|
return project.localization!.locales.flatMap(locale => getSearchSources(getLocalizedProject(project, locale.path)).map(source => ({ locale: locale.path, ...source })))
|
|
131
144
|
}
|
|
132
145
|
export async function GET(_request: Request, { params }: { params: Promise<{ locale: string, source: string }> }) { const { locale, source } = await params; return getSearchResponse(getLocalizedProject(await getProject(), locale), source) }
|
|
146
|
+
`
|
|
147
|
+
)
|
|
148
|
+
await emit(
|
|
149
|
+
'app/(rdx-locales)/[locale]/docs/llms.txt/route.ts',
|
|
150
|
+
`import { getLlmIndexResponse, getLocalizedProject } from '${provider}'
|
|
151
|
+
import { getProject } from '../../../../../rdx-project'
|
|
152
|
+
export const dynamic = 'force-static'
|
|
153
|
+
export const dynamicParams = false
|
|
154
|
+
export async function generateStaticParams() {
|
|
155
|
+
return (await getProject()).localization!.locales.map(locale => ({ locale: locale.path }))
|
|
156
|
+
}
|
|
157
|
+
export async function GET(_request: Request, { params }: { params: Promise<{ locale: string }> }) {
|
|
158
|
+
const project = await getProject()
|
|
159
|
+
const { locale } = await params
|
|
160
|
+
if (!project.localization?.locales.some(entry => entry.path === locale)) return new Response(null, { status: 404 })
|
|
161
|
+
return getLlmIndexResponse(getLocalizedProject(project, locale))
|
|
162
|
+
}
|
|
133
163
|
`
|
|
134
164
|
)
|
|
135
165
|
await writeFile(marker, JSON.stringify({ version: 1 }) + '\n')
|
package/config.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
createRdxProject,
|
|
7
7
|
resolveProjectPath,
|
|
8
8
|
getContentSources,
|
|
9
|
+
snapshotDatesFilename,
|
|
9
10
|
} from '@lexibase/rdx-core/config'
|
|
10
11
|
import { createJiti } from 'jiti'
|
|
11
12
|
|
|
@@ -49,7 +50,9 @@ async function contentFiles(directory) {
|
|
|
49
50
|
const filename = path.join(directory, entry.name)
|
|
50
51
|
if (entry.isDirectory()) return contentFiles(filename)
|
|
51
52
|
return entry.isFile() &&
|
|
52
|
-
(/\.mdx?$/.test(entry.name) ||
|
|
53
|
+
(/\.mdx?$/.test(entry.name) ||
|
|
54
|
+
entry.name === '_category.json' ||
|
|
55
|
+
entry.name === snapshotDatesFilename)
|
|
53
56
|
? [filename]
|
|
54
57
|
: []
|
|
55
58
|
})
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -21,6 +21,17 @@ declare function getRdxSitemap(project: RdxProject, { documentPath, }?: {
|
|
|
21
21
|
documentPath?: (source: RdxContentSource, page: RdxDocPage) => string;
|
|
22
22
|
}): MetadataRoute.Sitemap;
|
|
23
23
|
|
|
24
|
+
type DocumentPath = (source: RdxContentSource, page: Pick<RdxDocPage, 'slug' | 'sourcePath'>) => string;
|
|
25
|
+
declare function getMarkdownHref(htmlPath: string): string;
|
|
26
|
+
declare function getLlmIndexResponse(project: RdxProject, documentPath?: DocumentPath): Response;
|
|
27
|
+
declare function getMarkdownPaths(project: RdxProject, documentPath?: DocumentPath): {
|
|
28
|
+
path: string[];
|
|
29
|
+
}[];
|
|
30
|
+
declare function parseMarkdownPath(path: string[]): string[] | undefined;
|
|
31
|
+
declare function getMarkdownResponse(project: RdxProject, path: string[]): Response;
|
|
32
|
+
declare function markdownNotFound(): Response;
|
|
33
|
+
declare function getDocumentMarkdownResponse(project: RdxProject, source: RdxContentSource | undefined, slug: string, documentPath?: DocumentPath): Response;
|
|
34
|
+
|
|
24
35
|
/** Read metadata from the same content source and index used by the page. */
|
|
25
36
|
declare function getDocumentMetadata({ project, slug, }: {
|
|
26
37
|
project: RdxProject;
|
|
@@ -47,4 +58,4 @@ declare function DocsPage({ slug, project, }: {
|
|
|
47
58
|
project: RdxProject;
|
|
48
59
|
}): Promise<react.JSX.Element>;
|
|
49
60
|
|
|
50
|
-
export { DocsPage, HomePage, NotFoundPage, RdxLayout, getDocumentMetadata, getPageMetadata, getRdxMetadata, getRdxRobots, getRdxSitemap, getSearchResponse, getSearchSources, getSourceRobots };
|
|
61
|
+
export { DocsPage, HomePage, NotFoundPage, RdxLayout, getDocumentMarkdownResponse, getDocumentMetadata, getLlmIndexResponse, getMarkdownHref, getMarkdownPaths, getMarkdownResponse, getPageMetadata, getRdxMetadata, getRdxRobots, getRdxSitemap, getSearchResponse, getSearchSources, getSourceRobots, markdownNotFound, parseMarkdownPath };
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
// src/runtime/index.tsx
|
|
2
2
|
import {
|
|
3
|
-
getDocument as
|
|
3
|
+
getDocument as getDocument4,
|
|
4
4
|
getDocsPaths,
|
|
5
|
-
getSourceOptions as
|
|
5
|
+
getSourceOptions as getSourceOptions5,
|
|
6
6
|
resolveDocsRoute as resolveDocsRoute2,
|
|
7
|
-
getLocalizedProject as
|
|
8
|
-
getDocsHref as
|
|
7
|
+
getLocalizedProject as getLocalizedProject3,
|
|
8
|
+
getDocsHref as getDocsHref4,
|
|
9
9
|
getLanguageLinks,
|
|
10
|
-
isFallbackPage as
|
|
10
|
+
isFallbackPage as isFallbackPage4
|
|
11
11
|
} from "@lexibase/rdx-core";
|
|
12
|
+
import { getEditPageHref } from "@lexibase/rdx-core/config";
|
|
12
13
|
import { Button } from "@lexibase/rdx-ui/components/button";
|
|
13
14
|
import { Callout } from "@lexibase/rdx-ui/components/callout";
|
|
14
15
|
import { LanguageDropdown } from "@lexibase/rdx-ui/components/language-dropdown";
|
|
@@ -19,6 +20,8 @@ import { DocsSearch } from "@lexibase/rdx-ui/components/docs-search";
|
|
|
19
20
|
import { Home } from "@lexibase/rdx-ui/components/home";
|
|
20
21
|
import { SkipLink } from "@lexibase/rdx-ui/components/skip-link";
|
|
21
22
|
import { FooterCredit } from "@lexibase/rdx-ui/components/footer-credit";
|
|
23
|
+
import { EditPageLink } from "@lexibase/rdx-ui/components/edit-page-link";
|
|
24
|
+
import { CopyPage } from "@lexibase/rdx-ui/components/copy-page";
|
|
22
25
|
import { BrandLogo } from "@lexibase/rdx-ui/components/brand-logo";
|
|
23
26
|
import { getMdxComponents } from "@lexibase/rdx-ui/components/mdx-components";
|
|
24
27
|
import { getMessages, formatMessage } from "@lexibase/rdx-ui/lib/i18n";
|
|
@@ -61,19 +64,170 @@ function compileDocumentation(source, components, links) {
|
|
|
61
64
|
});
|
|
62
65
|
}
|
|
63
66
|
|
|
67
|
+
// src/runtime/markdown.ts
|
|
68
|
+
import {
|
|
69
|
+
getContentSources,
|
|
70
|
+
getDocsHref,
|
|
71
|
+
getDocsIndex,
|
|
72
|
+
getDocument,
|
|
73
|
+
getLocalizedProject,
|
|
74
|
+
getSourceOptions,
|
|
75
|
+
isFallbackPage
|
|
76
|
+
} from "@lexibase/rdx-core";
|
|
77
|
+
import { exportMarkdownBody } from "@lexibase/rdx-core/mdx";
|
|
78
|
+
import {
|
|
79
|
+
createDocumentDateReader,
|
|
80
|
+
getSnapshotDocumentDate
|
|
81
|
+
} from "@lexibase/rdx-core/config";
|
|
82
|
+
function publicUrl(project, path) {
|
|
83
|
+
const base = project.config.metadata.metadataBase;
|
|
84
|
+
return base ? new URL(path, base).href : path;
|
|
85
|
+
}
|
|
86
|
+
function indexPath(project) {
|
|
87
|
+
return `${project.locale ? `/${project.locale.path}` : ""}/docs/llms.txt`;
|
|
88
|
+
}
|
|
89
|
+
function defaultLocale(project) {
|
|
90
|
+
const locale = project.localization?.locales.find(
|
|
91
|
+
(entry) => entry.code === project.localization.defaultLocale
|
|
92
|
+
);
|
|
93
|
+
return !project.locale && locale ? getLocalizedProject(project, locale.path) : project;
|
|
94
|
+
}
|
|
95
|
+
function text(value) {
|
|
96
|
+
return value.replace(/\s+/g, " ").trim().replace(/[\\`*_[\]<>]/g, "\\$&");
|
|
97
|
+
}
|
|
98
|
+
function getMarkdownHref(htmlPath) {
|
|
99
|
+
return `/rdx-markdown${htmlPath}.md`;
|
|
100
|
+
}
|
|
101
|
+
function response(body, type, status = 200) {
|
|
102
|
+
return new Response(body, {
|
|
103
|
+
status,
|
|
104
|
+
headers: {
|
|
105
|
+
"Content-Type": `${type}; charset=utf-8`,
|
|
106
|
+
"X-Robots-Tag": "noindex, follow"
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function getLlmIndexResponse(project, documentPath) {
|
|
111
|
+
project = defaultLocale(project);
|
|
112
|
+
const source = project.sources.find(
|
|
113
|
+
(entry) => entry.id !== "current" && entry.redirectTo === void 0 && entry.badge !== "Archived"
|
|
114
|
+
) ?? project.sources[0];
|
|
115
|
+
const { metadata, description } = project.config;
|
|
116
|
+
const lines = [`# ${text(metadata.applicationName)} Documentation`, ""];
|
|
117
|
+
if (description) lines.push(`> ${text(description)}`, "");
|
|
118
|
+
if (source) {
|
|
119
|
+
for (const category of getDocsIndex(getSourceOptions(project, source))) {
|
|
120
|
+
const pages = category.pages.filter(
|
|
121
|
+
(page) => !isFallbackPage(project, source, page.sourcePath)
|
|
122
|
+
);
|
|
123
|
+
if (!pages.length) continue;
|
|
124
|
+
lines.push(`## ${text(category.title)}`, "");
|
|
125
|
+
for (const page of pages) {
|
|
126
|
+
const href = documentPath?.(source, page) ?? getDocsHref(project, source, page.slug);
|
|
127
|
+
lines.push(
|
|
128
|
+
`- [${text(page.title)}](<${publicUrl(project, getMarkdownHref(href))}>)${page.description ? `: ${text(page.description)}` : ""}`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
lines.push("");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return response(lines.join("\n"), "text/plain");
|
|
135
|
+
}
|
|
136
|
+
function getMarkdownPaths(project, documentPath) {
|
|
137
|
+
const paths = /* @__PURE__ */ new Set();
|
|
138
|
+
for (const source of getContentSources(project)) {
|
|
139
|
+
if (source.redirectTo !== void 0) continue;
|
|
140
|
+
for (const category of getDocsIndex(getSourceOptions(project, source))) {
|
|
141
|
+
for (const page of category.pages) {
|
|
142
|
+
if (isFallbackPage(project, source, page.sourcePath)) continue;
|
|
143
|
+
const href = documentPath?.(source, page) ?? getDocsHref(project, source, page.slug);
|
|
144
|
+
paths.add(`${href.slice(1)}.md`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return [...paths].map((path) => ({
|
|
149
|
+
path: path.split("/").map(decodeURIComponent)
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
function parseMarkdownPath(path) {
|
|
153
|
+
const last = path.at(-1);
|
|
154
|
+
return last?.endsWith(".md") && last.length > 3 ? [...path.slice(0, -1), last.slice(0, -3)] : void 0;
|
|
155
|
+
}
|
|
156
|
+
function getMarkdownResponse(project, path) {
|
|
157
|
+
const segments = parseMarkdownPath(path);
|
|
158
|
+
if (!segments) return markdownNotFound();
|
|
159
|
+
if (project.localization) {
|
|
160
|
+
const locale = segments.shift();
|
|
161
|
+
if (!project.localization.locales.some((entry) => entry.path === locale))
|
|
162
|
+
return markdownNotFound();
|
|
163
|
+
project = getLocalizedProject(project, locale);
|
|
164
|
+
}
|
|
165
|
+
if (segments.shift() !== "docs" || !segments.length) return markdownNotFound();
|
|
166
|
+
const edition = project.sources.find(
|
|
167
|
+
(source) => source.routePrefix && source.routePrefix === segments[0]
|
|
168
|
+
);
|
|
169
|
+
if (edition) segments.shift();
|
|
170
|
+
return getDocumentMarkdownResponse(
|
|
171
|
+
project,
|
|
172
|
+
edition ?? project.sources[0],
|
|
173
|
+
segments.join("/")
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
function markdownNotFound() {
|
|
177
|
+
return response(null, "text/markdown", 404);
|
|
178
|
+
}
|
|
179
|
+
function getDocumentMarkdownResponse(project, source, slug, documentPath) {
|
|
180
|
+
if (!source || !slug || source.redirectTo !== void 0)
|
|
181
|
+
return markdownNotFound();
|
|
182
|
+
const options = getSourceOptions(project, source);
|
|
183
|
+
const document = getDocument(slug, options);
|
|
184
|
+
if (!document || isFallbackPage(project, source, document.sourcePath))
|
|
185
|
+
return markdownNotFound();
|
|
186
|
+
const pages = getDocsIndex(options).flatMap((category) => category.pages);
|
|
187
|
+
const bySlug = new Map(pages.map((page2) => [page2.slug, page2]));
|
|
188
|
+
const href = (page2) => publicUrl(
|
|
189
|
+
project,
|
|
190
|
+
documentPath?.(source, page2) ?? getDocsHref(project, source, page2.slug)
|
|
191
|
+
);
|
|
192
|
+
const page = bySlug.get(document.slug);
|
|
193
|
+
const lastUpdated = source.version ? getSnapshotDocumentDate(options.docsDir, document.sourcePath) : createDocumentDateReader(project.rootDir)(document.sourcePath);
|
|
194
|
+
const frontmatter = {
|
|
195
|
+
title: page.title,
|
|
196
|
+
...page.description ? { description: page.description } : {},
|
|
197
|
+
url: href(document),
|
|
198
|
+
docs_index: publicUrl(project, indexPath(project)),
|
|
199
|
+
...lastUpdated ? { lastUpdated } : {}
|
|
200
|
+
};
|
|
201
|
+
const fields = Object.entries(frontmatter).map(
|
|
202
|
+
([key, value]) => `${key}: ${JSON.stringify(value)}`
|
|
203
|
+
);
|
|
204
|
+
const body = exportMarkdownBody(document.content, {
|
|
205
|
+
sourceRoot: options.docsDir,
|
|
206
|
+
sourcePath: document.sourcePath,
|
|
207
|
+
virtualPaths: !!options.fallbackDocsDir,
|
|
208
|
+
documents: pages,
|
|
209
|
+
documentHref: (slug2) => href(bySlug.get(slug2))
|
|
210
|
+
});
|
|
211
|
+
return response(`---
|
|
212
|
+
${fields.join("\n")}
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
${body}`, "text/markdown");
|
|
216
|
+
}
|
|
217
|
+
|
|
64
218
|
// src/runtime/index.tsx
|
|
65
219
|
import {
|
|
66
220
|
createRdxProject,
|
|
67
221
|
getProjectDocsPaths,
|
|
68
|
-
getLocalizedProject as
|
|
222
|
+
getLocalizedProject as getLocalizedProject4
|
|
69
223
|
} from "@lexibase/rdx-core";
|
|
70
224
|
|
|
71
225
|
// src/runtime/search.ts
|
|
72
226
|
import {
|
|
73
|
-
getDocsIndex,
|
|
74
|
-
getDocument,
|
|
75
|
-
getSourceOptions,
|
|
76
|
-
getDocsHref
|
|
227
|
+
getDocsIndex as getDocsIndex2,
|
|
228
|
+
getDocument as getDocument2,
|
|
229
|
+
getSourceOptions as getSourceOptions2,
|
|
230
|
+
getDocsHref as getDocsHref2
|
|
77
231
|
} from "@lexibase/rdx-core";
|
|
78
232
|
import { buildSearchIndex } from "@lexibase/rdx-core/search";
|
|
79
233
|
function getSearchSources(project) {
|
|
@@ -89,16 +243,16 @@ function getSearchResponse(project, key) {
|
|
|
89
243
|
if (!source) return new Response(null, { status: 404, headers });
|
|
90
244
|
if (source.fallbackOnly)
|
|
91
245
|
return Response.json(buildSearchIndex([]), { headers });
|
|
92
|
-
const { docsDir } =
|
|
246
|
+
const { docsDir } = getSourceOptions2(project, source);
|
|
93
247
|
const options = { docsDir };
|
|
94
|
-
const documents =
|
|
248
|
+
const documents = getDocsIndex2(options).flatMap(
|
|
95
249
|
(category) => category.pages.map((page) => ({
|
|
96
250
|
title: page.title,
|
|
97
251
|
description: page.description,
|
|
98
252
|
category: category.title,
|
|
99
|
-
href:
|
|
253
|
+
href: getDocsHref2(project, source, page.slug),
|
|
100
254
|
sourcePath: page.sourcePath,
|
|
101
|
-
content:
|
|
255
|
+
content: getDocument2(page.slug, options)?.content ?? ""
|
|
102
256
|
}))
|
|
103
257
|
);
|
|
104
258
|
return Response.json(buildSearchIndex(documents), { headers });
|
|
@@ -106,10 +260,10 @@ function getSearchResponse(project, key) {
|
|
|
106
260
|
|
|
107
261
|
// src/runtime/indexing.ts
|
|
108
262
|
import {
|
|
109
|
-
getDocsIndex as
|
|
110
|
-
getSourceOptions as
|
|
111
|
-
getContentSources,
|
|
112
|
-
isFallbackPage
|
|
263
|
+
getDocsIndex as getDocsIndex3,
|
|
264
|
+
getSourceOptions as getSourceOptions3,
|
|
265
|
+
getContentSources as getContentSources2,
|
|
266
|
+
isFallbackPage as isFallbackPage2
|
|
113
267
|
} from "@lexibase/rdx-core";
|
|
114
268
|
function getSourceRobots(project, source) {
|
|
115
269
|
const published = project.sources.some(
|
|
@@ -138,11 +292,11 @@ function getRdxSitemap(project, {
|
|
|
138
292
|
if (!base) return [];
|
|
139
293
|
const urls = /* @__PURE__ */ new Set();
|
|
140
294
|
if (project.config.homepage?.enabled) urls.add(new URL("/", base).href);
|
|
141
|
-
for (const source of
|
|
295
|
+
for (const source of getContentSources2(project)) {
|
|
142
296
|
if (!getSourceRobots(project, source).index) continue;
|
|
143
|
-
for (const category of
|
|
297
|
+
for (const category of getDocsIndex3(getSourceOptions3(project, source))) {
|
|
144
298
|
for (const page of category.pages) {
|
|
145
|
-
if (
|
|
299
|
+
if (isFallbackPage2(project, source, page.sourcePath)) continue;
|
|
146
300
|
urls.add(new URL(documentPath(source, page), base).href);
|
|
147
301
|
}
|
|
148
302
|
}
|
|
@@ -153,11 +307,11 @@ function getRdxSitemap(project, {
|
|
|
153
307
|
// src/runtime/metadata.ts
|
|
154
308
|
import {
|
|
155
309
|
resolveDocsRoute,
|
|
156
|
-
getLocalizedProject,
|
|
157
|
-
getDocsHref as
|
|
158
|
-
isFallbackPage as
|
|
159
|
-
getDocument as
|
|
160
|
-
getSourceOptions as
|
|
310
|
+
getLocalizedProject as getLocalizedProject2,
|
|
311
|
+
getDocsHref as getDocsHref3,
|
|
312
|
+
isFallbackPage as isFallbackPage3,
|
|
313
|
+
getDocument as getDocument3,
|
|
314
|
+
getSourceOptions as getSourceOptions4
|
|
161
315
|
} from "@lexibase/rdx-core";
|
|
162
316
|
import { notFound } from "next/navigation";
|
|
163
317
|
function getDocumentMetadata({
|
|
@@ -172,24 +326,24 @@ function getDocumentMetadata({
|
|
|
172
326
|
if (!route.slug) return { robots: { index: false, follow: true } };
|
|
173
327
|
if (!route.document) notFound();
|
|
174
328
|
const page = route.categories.flatMap((category) => category.pages).find((page2) => page2.slug === route.slug);
|
|
175
|
-
const fallback =
|
|
329
|
+
const fallback = isFallbackPage3(project, route.source, page.sourcePath);
|
|
176
330
|
const primary = project.localization?.locales.find(
|
|
177
331
|
(locale) => locale.code === project.localization.defaultLocale
|
|
178
332
|
);
|
|
179
|
-
const canonicalProject = fallback ?
|
|
333
|
+
const canonicalProject = fallback ? getLocalizedProject2(project, primary.path) : project;
|
|
180
334
|
const base = project.config.metadata.metadataBase;
|
|
181
335
|
const languages = project.localization && base ? Object.fromEntries(
|
|
182
336
|
project.localization.locales.flatMap((locale) => {
|
|
183
|
-
const view =
|
|
337
|
+
const view = getLocalizedProject2(project, locale.path);
|
|
184
338
|
const source = view.sources.find(
|
|
185
339
|
(entry) => entry.id === route.source.id
|
|
186
340
|
);
|
|
187
|
-
return !source.fallbackOnly &&
|
|
188
|
-
docsDir:
|
|
341
|
+
return !source.fallbackOnly && getDocument3(page.slug, {
|
|
342
|
+
docsDir: getSourceOptions4(view, source).docsDir
|
|
189
343
|
}) ? [
|
|
190
344
|
[
|
|
191
345
|
locale.code,
|
|
192
|
-
new URL(
|
|
346
|
+
new URL(getDocsHref3(view, source, page.slug), base).href
|
|
193
347
|
]
|
|
194
348
|
] : [];
|
|
195
349
|
})
|
|
@@ -200,7 +354,7 @@ function getDocumentMetadata({
|
|
|
200
354
|
...project.localization && base ? {
|
|
201
355
|
alternates: {
|
|
202
356
|
canonical: new URL(
|
|
203
|
-
|
|
357
|
+
getDocsHref3(
|
|
204
358
|
canonicalProject,
|
|
205
359
|
canonicalProject.sources.find(
|
|
206
360
|
(entry) => entry.id === route.source.id
|
|
@@ -280,13 +434,13 @@ function RdxHeader({
|
|
|
280
434
|
const messages = getMessages(config.lang);
|
|
281
435
|
const { source, slug: currentSlug } = resolveDocsRoute2(project, slug);
|
|
282
436
|
const options = project.sources.filter((edition) => edition.redirectTo === void 0).map((edition) => {
|
|
283
|
-
const docs =
|
|
284
|
-
const destination = currentSlug &&
|
|
437
|
+
const docs = getSourceOptions5(project, edition);
|
|
438
|
+
const destination = currentSlug && getDocument4(currentSlug, docs) ? currentSlug : getDocsPaths(docs)[0];
|
|
285
439
|
return {
|
|
286
440
|
id: edition.id,
|
|
287
441
|
label: edition.id === "current" ? messages.current : formatMessage(messages.version, { version: edition.label }),
|
|
288
442
|
kind: edition.id === "current" ? "live" : edition.badge === "Archived" ? "archived" : "version",
|
|
289
|
-
href:
|
|
443
|
+
href: getDocsHref4(project, edition, destination)
|
|
290
444
|
};
|
|
291
445
|
});
|
|
292
446
|
return /* @__PURE__ */ jsx(
|
|
@@ -303,8 +457,8 @@ function RdxHeader({
|
|
|
303
457
|
) : void 0,
|
|
304
458
|
siteTitle: config.metadata.applicationName,
|
|
305
459
|
logo: /* @__PURE__ */ jsx(BrandLogo, { source: config.navbar?.logo, className: "size-5" }),
|
|
306
|
-
homeHref: config.homepage?.enabled ? "/" :
|
|
307
|
-
docsHref:
|
|
460
|
+
homeHref: config.homepage?.enabled ? "/" : getDocsHref4(project),
|
|
461
|
+
docsHref: getDocsHref4(project, source),
|
|
308
462
|
languageMenu: project.localization ? /* @__PURE__ */ jsx(
|
|
309
463
|
LanguageDropdown,
|
|
310
464
|
{
|
|
@@ -322,7 +476,7 @@ function RdxHeader({
|
|
|
322
476
|
}
|
|
323
477
|
function HomePage({ project }) {
|
|
324
478
|
const { config } = project;
|
|
325
|
-
if (!config.homepage?.enabled) redirect(
|
|
479
|
+
if (!config.homepage?.enabled) redirect(getDocsHref4(project));
|
|
326
480
|
const homepage = config.homepage;
|
|
327
481
|
const CustomHome = homepage.component;
|
|
328
482
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -381,7 +535,7 @@ async function DocsPage({
|
|
|
381
535
|
project
|
|
382
536
|
}) {
|
|
383
537
|
if (project.localization && !project.locale)
|
|
384
|
-
permanentRedirect(
|
|
538
|
+
permanentRedirect(getDocsHref4(project, project.sources[0], slug?.join("/")));
|
|
385
539
|
const messages = getMessages(project.config.lang);
|
|
386
540
|
const {
|
|
387
541
|
source,
|
|
@@ -391,7 +545,7 @@ async function DocsPage({
|
|
|
391
545
|
} = resolveDocsRoute2(project, slug);
|
|
392
546
|
if (source.redirectTo !== void 0)
|
|
393
547
|
permanentRedirect(
|
|
394
|
-
|
|
548
|
+
getDocsHref4(
|
|
395
549
|
project,
|
|
396
550
|
project.sources.find(
|
|
397
551
|
(entry) => entry.routePrefix === source.redirectTo
|
|
@@ -408,15 +562,16 @@ async function DocsPage({
|
|
|
408
562
|
] })
|
|
409
563
|
] });
|
|
410
564
|
if (!document) notFound2();
|
|
411
|
-
const fallback =
|
|
565
|
+
const fallback = isFallbackPage4(project, source, document.sourcePath);
|
|
566
|
+
const editHref = fallback ? void 0 : getEditPageHref(project, source, document.sourcePath);
|
|
412
567
|
const primaryLocale = (source.localization ?? project.localization)?.locales.find(
|
|
413
568
|
(locale) => locale.code === project.localization.defaultLocale
|
|
414
569
|
);
|
|
415
|
-
const originalProject = fallback && primaryLocale ?
|
|
570
|
+
const originalProject = fallback && primaryLocale ? getLocalizedProject3(project, primaryLocale.path) : project;
|
|
416
571
|
const contentSource = originalProject.sources.find(
|
|
417
572
|
(entry) => entry.id === source.id
|
|
418
573
|
);
|
|
419
|
-
const contentOptions =
|
|
574
|
+
const contentOptions = getSourceOptions5(originalProject, contentSource);
|
|
420
575
|
const contentCategories = fallback ? resolveDocsRoute2(originalProject, slug).categories : categories;
|
|
421
576
|
const contentLanguage = fallback ? primaryLocale.code : project.config.lang;
|
|
422
577
|
const { content } = await compileDocumentation(
|
|
@@ -431,18 +586,20 @@ async function DocsPage({
|
|
|
431
586
|
documents: contentCategories.flatMap((category2) => category2.pages)
|
|
432
587
|
}
|
|
433
588
|
);
|
|
434
|
-
const title = typeof document.frontmatter.title === "string" ? document.frontmatter.title : currentSlug;
|
|
435
589
|
const description = typeof document.frontmatter.description === "string" ? document.frontmatter.description : null;
|
|
436
|
-
const hrefFor = (pageSlug) =>
|
|
590
|
+
const hrefFor = (pageSlug) => getDocsHref4(project, source, pageSlug);
|
|
591
|
+
const markdownHref = fallback ? void 0 : getMarkdownHref(hrefFor(currentSlug));
|
|
437
592
|
const sidebarCategories = categories.map((category2) => ({
|
|
438
593
|
title: category2.title,
|
|
439
594
|
links: category2.pages.map((page) => ({
|
|
440
|
-
label: page.title,
|
|
595
|
+
label: page.navTitle ?? page.title,
|
|
596
|
+
highlighting: page.highlighting,
|
|
441
597
|
href: hrefFor(page.slug)
|
|
442
598
|
}))
|
|
443
599
|
}));
|
|
444
600
|
const pages = categories.flatMap((category2) => category2.pages);
|
|
445
601
|
const index = pages.findIndex((page) => page.slug === currentSlug);
|
|
602
|
+
const title = pages[index]?.title ?? currentSlug;
|
|
446
603
|
const previous = pages[index - 1];
|
|
447
604
|
const next = pages[index + 1];
|
|
448
605
|
const category = categories.find(
|
|
@@ -500,7 +657,7 @@ async function DocsPage({
|
|
|
500
657
|
Button,
|
|
501
658
|
{
|
|
502
659
|
variant: "link",
|
|
503
|
-
href:
|
|
660
|
+
href: getDocsHref4(
|
|
504
661
|
originalProject,
|
|
505
662
|
contentSource,
|
|
506
663
|
currentSlug
|
|
@@ -534,14 +691,18 @@ async function DocsPage({
|
|
|
534
691
|
/* @__PURE__ */ jsxs("header", { className: "mb-6", children: [
|
|
535
692
|
source.badge && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4", children: source.badge === "Archived" ? messages.archivedVersion : source.badge }),
|
|
536
693
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-zinc-600 font-semibold uppercase block -mb-0.5", children: category?.title }),
|
|
537
|
-
/* @__PURE__ */
|
|
538
|
-
|
|
694
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex flex-wrap items-start gap-x-4 gap-y-2", children: [
|
|
695
|
+
/* @__PURE__ */ jsx("h1", { className: "min-w-0 max-w-full break-words text-4xl font-bold uppercase", children: title }),
|
|
696
|
+
markdownHref && /* @__PURE__ */ jsx(CopyPage, { href: markdownHref }, markdownHref)
|
|
697
|
+
] }),
|
|
698
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-[726px]", children: description })
|
|
539
699
|
] }),
|
|
540
700
|
/* @__PURE__ */ jsx("div", { className: "h-full w-full flex-1 max-w-[960px]", children: content })
|
|
541
701
|
]
|
|
542
702
|
}
|
|
543
703
|
),
|
|
544
704
|
/* @__PURE__ */ jsxs("footer", { className: "flex flex-col", children: [
|
|
705
|
+
editHref && /* @__PURE__ */ jsx(EditPageLink, { href: editHref, lang: project.config.lang }),
|
|
545
706
|
/* @__PURE__ */ jsxs("section", { className: "flex items-center justify-between", children: [
|
|
546
707
|
previous ? /* @__PURE__ */ jsx(
|
|
547
708
|
Button,
|
|
@@ -590,8 +751,13 @@ export {
|
|
|
590
751
|
NotFoundPage,
|
|
591
752
|
RdxLayout,
|
|
592
753
|
createRdxProject,
|
|
754
|
+
getDocumentMarkdownResponse,
|
|
593
755
|
getDocumentMetadata,
|
|
594
|
-
|
|
756
|
+
getLlmIndexResponse,
|
|
757
|
+
getLocalizedProject4 as getLocalizedProject,
|
|
758
|
+
getMarkdownHref,
|
|
759
|
+
getMarkdownPaths,
|
|
760
|
+
getMarkdownResponse,
|
|
595
761
|
getPageMetadata,
|
|
596
762
|
getProjectDocsPaths,
|
|
597
763
|
getRdxMetadata,
|
|
@@ -599,5 +765,7 @@ export {
|
|
|
599
765
|
getRdxSitemap,
|
|
600
766
|
getSearchResponse,
|
|
601
767
|
getSearchSources,
|
|
602
|
-
getSourceRobots
|
|
768
|
+
getSourceRobots,
|
|
769
|
+
markdownNotFound,
|
|
770
|
+
parseMarkdownPath
|
|
603
771
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lexibase/rdx-next",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "The Next.js runtime for RDX documentation projects.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"next-mdx-remote": "^6.0.0",
|
|
53
53
|
"remark-gfm": "^4",
|
|
54
54
|
"typescript": "6.0.3",
|
|
55
|
-
"@lexibase/rdx-
|
|
56
|
-
"@lexibase/rdx-
|
|
55
|
+
"@lexibase/rdx-core": "3.0.1",
|
|
56
|
+
"@lexibase/rdx-types": "2.3.0"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@lexibase/rdx-ui": "^3.
|
|
59
|
+
"@lexibase/rdx-ui": "^3.5.0",
|
|
60
60
|
"next": "^16.4.2",
|
|
61
61
|
"react": "^19.3.1",
|
|
62
62
|
"react-dom": "^19.3.1"
|
|
@@ -81,9 +81,9 @@
|
|
|
81
81
|
"next": "^16.4.2",
|
|
82
82
|
"react": "19.3.1",
|
|
83
83
|
"react-dom": "19.3.1",
|
|
84
|
-
"@rdx
|
|
84
|
+
"@lexibase/rdx-ui": "3.5.1",
|
|
85
85
|
"@rdx/eslint-config": "1.0.0",
|
|
86
|
-
"@
|
|
86
|
+
"@rdx/typescript-config": "1.0.0"
|
|
87
87
|
},
|
|
88
88
|
"scripts": {
|
|
89
89
|
"dev": "tsup src/index.ts src/runtime/index.tsx --format esm --dts --watch --external @lexibase/rdx-core --external @lexibase/rdx-types --external @lexibase/rdx-ui --external next --external react --external react-dom --external next-mdx-remote",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getMarkdownPaths,
|
|
3
|
+
getMarkdownResponse,
|
|
4
|
+
} from '@lexibase/rdx-next/runtime'
|
|
5
|
+
import { getProject } from '../../../rdx-project'
|
|
6
|
+
|
|
7
|
+
export const dynamic = 'force-static'
|
|
8
|
+
export const dynamicParams = false
|
|
9
|
+
|
|
10
|
+
export async function generateStaticParams() {
|
|
11
|
+
return getMarkdownPaths(await getProject())
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function GET(
|
|
15
|
+
_request: Request,
|
|
16
|
+
{ params }: { params: Promise<{ path: string[] }> }
|
|
17
|
+
) {
|
|
18
|
+
return getMarkdownResponse(await getProject(), (await params).path)
|
|
19
|
+
}
|