@farming-labs/docs 0.0.29 → 0.0.31
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/dist/cli/index.mjs +251 -17
- package/dist/index.d.mts +28 -1
- package/dist/index.mjs +41 -1
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -226,6 +226,14 @@ const THEME_INFO = {
|
|
|
226
226
|
function getThemeInfo(theme) {
|
|
227
227
|
return THEME_INFO[theme] ?? THEME_INFO.fumadocs;
|
|
228
228
|
}
|
|
229
|
+
function renderI18nConfig(cfg, indent = " ") {
|
|
230
|
+
const i18n = cfg.i18n;
|
|
231
|
+
if (!i18n || i18n.locales.length === 0) return "";
|
|
232
|
+
return `${indent}i18n: {\n${indent} locales: [${i18n.locales.map((locale) => `"${locale}"`).join(", ")}],\n${indent} defaultLocale: "${i18n.defaultLocale}",\n${indent}},\n`;
|
|
233
|
+
}
|
|
234
|
+
function toLocaleImportName(locale) {
|
|
235
|
+
return `LocalePage_${locale.replace(/[^a-zA-Z0-9_$]/g, "_")}`;
|
|
236
|
+
}
|
|
229
237
|
function getThemeExportName(themeName) {
|
|
230
238
|
const base = themeName.replace(/\.ts$/i, "").trim();
|
|
231
239
|
if (!base) return "customTheme";
|
|
@@ -315,7 +323,7 @@ import { ${exportName} } from "${cfg.useAlias ? "@/themes/" + cfg.customThemeNam
|
|
|
315
323
|
|
|
316
324
|
export default defineDocs({
|
|
317
325
|
entry: "${cfg.entry}",
|
|
318
|
-
theme: ${exportName}({
|
|
326
|
+
${renderI18nConfig(cfg)} theme: ${exportName}({
|
|
319
327
|
ui: {
|
|
320
328
|
colors: { primary: "#6366f1" },
|
|
321
329
|
},
|
|
@@ -335,7 +343,7 @@ import { ${t.factory} } from "${t.nextImport}";
|
|
|
335
343
|
|
|
336
344
|
export default defineDocs({
|
|
337
345
|
entry: "${cfg.entry}",
|
|
338
|
-
theme: ${t.factory}({
|
|
346
|
+
${renderI18nConfig(cfg)} theme: ${t.factory}({
|
|
339
347
|
ui: {
|
|
340
348
|
colors: { primary: "#6366f1" },
|
|
341
349
|
},
|
|
@@ -473,6 +481,48 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
|
|
473
481
|
}
|
|
474
482
|
`;
|
|
475
483
|
}
|
|
484
|
+
function nextLocaleDocPageTemplate(defaultLocale) {
|
|
485
|
+
return `\
|
|
486
|
+
import type { ComponentType } from "react";
|
|
487
|
+
|
|
488
|
+
type SearchParams = Promise<{ lang?: string | string[] | undefined }> | undefined;
|
|
489
|
+
|
|
490
|
+
function normalizeLang(value: string | string[] | undefined) {
|
|
491
|
+
return Array.isArray(value) ? value[0] : value;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export async function resolveLocaleDocPage<T extends ComponentType>(
|
|
495
|
+
searchParams: SearchParams,
|
|
496
|
+
pages: Record<string, T>,
|
|
497
|
+
fallbackLocale = "${defaultLocale}",
|
|
498
|
+
) {
|
|
499
|
+
const params = (await searchParams) ?? {};
|
|
500
|
+
const locale = normalizeLang(params.lang) ?? fallbackLocale;
|
|
501
|
+
|
|
502
|
+
return pages[locale] ?? pages[fallbackLocale];
|
|
503
|
+
}
|
|
504
|
+
`;
|
|
505
|
+
}
|
|
506
|
+
function nextLocalizedPageTemplate(options) {
|
|
507
|
+
const importLines = options.pageImports.map(({ locale, importPath }) => `import ${toLocaleImportName(locale)} from "${importPath}";`).join("\n");
|
|
508
|
+
const pageMap = options.pageImports.map(({ locale }) => ` ${JSON.stringify(locale)}: ${toLocaleImportName(locale)},`).join("\n");
|
|
509
|
+
return `\
|
|
510
|
+
${importLines}
|
|
511
|
+
import { resolveLocaleDocPage } from "${options.helperImport}";
|
|
512
|
+
|
|
513
|
+
type PageProps = {
|
|
514
|
+
searchParams?: Promise<{ lang?: string | string[] | undefined }>;
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
export default async function ${options.componentName}({ searchParams }: PageProps) {
|
|
518
|
+
const Page = await resolveLocaleDocPage(searchParams, {
|
|
519
|
+
${pageMap}
|
|
520
|
+
}, "${options.defaultLocale}");
|
|
521
|
+
|
|
522
|
+
return <Page />;
|
|
523
|
+
}
|
|
524
|
+
`;
|
|
525
|
+
}
|
|
476
526
|
function postcssConfigTemplate() {
|
|
477
527
|
return `\
|
|
478
528
|
const config = {
|
|
@@ -696,7 +746,8 @@ import { ${exportName} } from "${"../../themes/" + cfg.customThemeName.replace(/
|
|
|
696
746
|
|
|
697
747
|
export default defineDocs({
|
|
698
748
|
entry: "${cfg.entry}",
|
|
699
|
-
|
|
749
|
+
contentDir: "${cfg.entry}",
|
|
750
|
+
${renderI18nConfig(cfg)} theme: ${exportName}({
|
|
700
751
|
ui: {
|
|
701
752
|
colors: { primary: "#6366f1" },
|
|
702
753
|
},
|
|
@@ -723,7 +774,8 @@ import { ${t.factory} } from "${t.svelteImport}";
|
|
|
723
774
|
|
|
724
775
|
export default defineDocs({
|
|
725
776
|
entry: "${cfg.entry}",
|
|
726
|
-
|
|
777
|
+
contentDir: "${cfg.entry}",
|
|
778
|
+
${renderI18nConfig(cfg)} theme: ${t.factory}({
|
|
727
779
|
ui: {
|
|
728
780
|
colors: { primary: "#6366f1" },
|
|
729
781
|
},
|
|
@@ -1005,7 +1057,7 @@ import { ${exportName} } from "${"../../themes/" + cfg.customThemeName.replace(/
|
|
|
1005
1057
|
export default defineDocs({
|
|
1006
1058
|
entry: "${cfg.entry}",
|
|
1007
1059
|
contentDir: "${cfg.entry}",
|
|
1008
|
-
theme: ${exportName}({
|
|
1060
|
+
${renderI18nConfig(cfg)} theme: ${exportName}({
|
|
1009
1061
|
ui: {
|
|
1010
1062
|
colors: { primary: "#6366f1" },
|
|
1011
1063
|
},
|
|
@@ -1033,7 +1085,7 @@ import { ${t.factory} } from "${t.astroImport}";
|
|
|
1033
1085
|
export default defineDocs({
|
|
1034
1086
|
entry: "${cfg.entry}",
|
|
1035
1087
|
contentDir: "${cfg.entry}",
|
|
1036
|
-
theme: ${t.factory}({
|
|
1088
|
+
${renderI18nConfig(cfg)} theme: ${t.factory}({
|
|
1037
1089
|
ui: {
|
|
1038
1090
|
colors: { primary: "#6366f1" },
|
|
1039
1091
|
},
|
|
@@ -1361,7 +1413,7 @@ import { ${exportName} } from "${cfg.useAlias ? "~/themes/" + cfg.customThemeNam
|
|
|
1361
1413
|
export default defineDocs({
|
|
1362
1414
|
entry: "${cfg.entry}",
|
|
1363
1415
|
contentDir: "${cfg.entry}",
|
|
1364
|
-
theme: ${exportName}({
|
|
1416
|
+
${renderI18nConfig(cfg)} theme: ${exportName}({
|
|
1365
1417
|
ui: {
|
|
1366
1418
|
colors: { primary: "#6366f1" },
|
|
1367
1419
|
},
|
|
@@ -1389,7 +1441,7 @@ import { ${t.factory} } from "${t.nuxtImport}";
|
|
|
1389
1441
|
export default defineDocs({
|
|
1390
1442
|
entry: "${cfg.entry}",
|
|
1391
1443
|
contentDir: "${cfg.entry}",
|
|
1392
|
-
theme: ${t.factory}({
|
|
1444
|
+
${renderI18nConfig(cfg)} theme: ${t.factory}({
|
|
1393
1445
|
ui: {
|
|
1394
1446
|
colors: { primary: "#6366f1" },
|
|
1395
1447
|
},
|
|
@@ -1713,6 +1765,79 @@ const VALID_TEMPLATES = [
|
|
|
1713
1765
|
"sveltekit",
|
|
1714
1766
|
"astro"
|
|
1715
1767
|
];
|
|
1768
|
+
const COMMON_LOCALE_OPTIONS = [
|
|
1769
|
+
{
|
|
1770
|
+
value: "en",
|
|
1771
|
+
label: "English",
|
|
1772
|
+
hint: "en"
|
|
1773
|
+
},
|
|
1774
|
+
{
|
|
1775
|
+
value: "fr",
|
|
1776
|
+
label: "French",
|
|
1777
|
+
hint: "fr"
|
|
1778
|
+
},
|
|
1779
|
+
{
|
|
1780
|
+
value: "es",
|
|
1781
|
+
label: "Spanish",
|
|
1782
|
+
hint: "es"
|
|
1783
|
+
},
|
|
1784
|
+
{
|
|
1785
|
+
value: "de",
|
|
1786
|
+
label: "German",
|
|
1787
|
+
hint: "de"
|
|
1788
|
+
},
|
|
1789
|
+
{
|
|
1790
|
+
value: "pt",
|
|
1791
|
+
label: "Portuguese",
|
|
1792
|
+
hint: "pt"
|
|
1793
|
+
},
|
|
1794
|
+
{
|
|
1795
|
+
value: "it",
|
|
1796
|
+
label: "Italian",
|
|
1797
|
+
hint: "it"
|
|
1798
|
+
},
|
|
1799
|
+
{
|
|
1800
|
+
value: "ja",
|
|
1801
|
+
label: "Japanese",
|
|
1802
|
+
hint: "ja"
|
|
1803
|
+
},
|
|
1804
|
+
{
|
|
1805
|
+
value: "ko",
|
|
1806
|
+
label: "Korean",
|
|
1807
|
+
hint: "ko"
|
|
1808
|
+
},
|
|
1809
|
+
{
|
|
1810
|
+
value: "zh",
|
|
1811
|
+
label: "Chinese",
|
|
1812
|
+
hint: "zh"
|
|
1813
|
+
},
|
|
1814
|
+
{
|
|
1815
|
+
value: "ar",
|
|
1816
|
+
label: "Arabic",
|
|
1817
|
+
hint: "ar"
|
|
1818
|
+
},
|
|
1819
|
+
{
|
|
1820
|
+
value: "hi",
|
|
1821
|
+
label: "Hindi",
|
|
1822
|
+
hint: "hi"
|
|
1823
|
+
},
|
|
1824
|
+
{
|
|
1825
|
+
value: "ru",
|
|
1826
|
+
label: "Russian",
|
|
1827
|
+
hint: "ru"
|
|
1828
|
+
}
|
|
1829
|
+
];
|
|
1830
|
+
function normalizeLocaleCode(value) {
|
|
1831
|
+
const trimmed = value.trim();
|
|
1832
|
+
if (!trimmed) return "";
|
|
1833
|
+
const [language, ...rest] = trimmed.split("-");
|
|
1834
|
+
const normalizedLanguage = language.toLowerCase();
|
|
1835
|
+
if (rest.length === 0) return normalizedLanguage;
|
|
1836
|
+
return `${normalizedLanguage}-${rest.join("-").toUpperCase()}`;
|
|
1837
|
+
}
|
|
1838
|
+
function parseLocaleInput(input) {
|
|
1839
|
+
return Array.from(new Set(input.split(",").map((value) => normalizeLocaleCode(value)).filter(Boolean)));
|
|
1840
|
+
}
|
|
1716
1841
|
async function init(options = {}) {
|
|
1717
1842
|
const cwd = process.cwd();
|
|
1718
1843
|
p.intro(pc.bgCyan(pc.black(" @farming-labs/docs ")));
|
|
@@ -2032,6 +2157,64 @@ async function init(options = {}) {
|
|
|
2032
2157
|
process.exit(0);
|
|
2033
2158
|
}
|
|
2034
2159
|
const entryPath = entry.trim() || defaultEntry;
|
|
2160
|
+
const enableI18n = await p.confirm({
|
|
2161
|
+
message: "Do you want to scaffold internationalized docs with locale folders?",
|
|
2162
|
+
initialValue: false
|
|
2163
|
+
});
|
|
2164
|
+
if (p.isCancel(enableI18n)) {
|
|
2165
|
+
p.outro(pc.red("Init cancelled."));
|
|
2166
|
+
process.exit(0);
|
|
2167
|
+
}
|
|
2168
|
+
let docsI18n;
|
|
2169
|
+
if (enableI18n) {
|
|
2170
|
+
const selectedLocales = await p.multiselect({
|
|
2171
|
+
message: "Which languages should we scaffold?",
|
|
2172
|
+
options: COMMON_LOCALE_OPTIONS.map((option) => ({
|
|
2173
|
+
value: option.value,
|
|
2174
|
+
label: option.label,
|
|
2175
|
+
hint: option.hint
|
|
2176
|
+
}))
|
|
2177
|
+
});
|
|
2178
|
+
if (p.isCancel(selectedLocales)) {
|
|
2179
|
+
p.outro(pc.red("Init cancelled."));
|
|
2180
|
+
process.exit(0);
|
|
2181
|
+
}
|
|
2182
|
+
const extraLocalesAnswer = await p.text({
|
|
2183
|
+
message: "Any additional locale codes? (comma-separated, optional)",
|
|
2184
|
+
placeholder: "nl, sv, pt-BR",
|
|
2185
|
+
defaultValue: "",
|
|
2186
|
+
validate: (value) => {
|
|
2187
|
+
return parseLocaleInput(value ?? "").every((locale) => /^[a-z]{2,3}(?:-[A-Z]{2})?$/.test(locale)) ? void 0 : "Use locale codes like en, fr, zh, or pt-BR";
|
|
2188
|
+
}
|
|
2189
|
+
});
|
|
2190
|
+
if (p.isCancel(extraLocalesAnswer)) {
|
|
2191
|
+
p.outro(pc.red("Init cancelled."));
|
|
2192
|
+
process.exit(0);
|
|
2193
|
+
}
|
|
2194
|
+
const locales = Array.from(new Set([...(selectedLocales ?? []).map((locale) => normalizeLocaleCode(locale)), ...parseLocaleInput(extraLocalesAnswer ?? "")])).filter(Boolean);
|
|
2195
|
+
if (locales.length === 0) {
|
|
2196
|
+
p.log.error("Pick at least one locale to scaffold i18n support.");
|
|
2197
|
+
p.outro(pc.red("Init cancelled."));
|
|
2198
|
+
process.exit(1);
|
|
2199
|
+
}
|
|
2200
|
+
const defaultLocaleAnswer = await p.select({
|
|
2201
|
+
message: "Which locale should be the default?",
|
|
2202
|
+
options: locales.map((locale) => ({
|
|
2203
|
+
value: locale,
|
|
2204
|
+
label: locale,
|
|
2205
|
+
hint: locale === "en" ? "Recommended default" : void 0
|
|
2206
|
+
})),
|
|
2207
|
+
initialValue: locales[0]
|
|
2208
|
+
});
|
|
2209
|
+
if (p.isCancel(defaultLocaleAnswer)) {
|
|
2210
|
+
p.outro(pc.red("Init cancelled."));
|
|
2211
|
+
process.exit(0);
|
|
2212
|
+
}
|
|
2213
|
+
docsI18n = {
|
|
2214
|
+
locales,
|
|
2215
|
+
defaultLocale: defaultLocaleAnswer
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2035
2218
|
const detectedCssFiles = detectGlobalCssFiles(cwd);
|
|
2036
2219
|
let globalCssRelPath;
|
|
2037
2220
|
const defaultCssPath = framework === "sveltekit" ? "src/app.css" : framework === "astro" ? "src/styles/global.css" : framework === "nuxt" ? "assets/css/main.css" : framework === "nextjs" ? `${nextAppDir}/globals.css` : "app/globals.css";
|
|
@@ -2078,6 +2261,7 @@ async function init(options = {}) {
|
|
|
2078
2261
|
framework,
|
|
2079
2262
|
useAlias,
|
|
2080
2263
|
astroAdapter,
|
|
2264
|
+
i18n: docsI18n,
|
|
2081
2265
|
...framework === "nextjs" && { nextAppDir }
|
|
2082
2266
|
};
|
|
2083
2267
|
const s = p.spinner();
|
|
@@ -2219,6 +2403,9 @@ async function init(options = {}) {
|
|
|
2219
2403
|
process.exit(1);
|
|
2220
2404
|
}
|
|
2221
2405
|
}
|
|
2406
|
+
function getScaffoldContentRoots(cfg) {
|
|
2407
|
+
return cfg.i18n?.locales?.length ? cfg.i18n.locales.map((locale) => `${cfg.entry}/${locale}`) : [cfg.entry];
|
|
2408
|
+
}
|
|
2222
2409
|
function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
2223
2410
|
const appDir = cfg.nextAppDir ?? "app";
|
|
2224
2411
|
if (cfg.theme === "custom" && cfg.customThemeName) {
|
|
@@ -2258,6 +2445,46 @@ function scaffoldNextJs(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
2258
2445
|
write(`${appDir}/${cfg.entry}/layout.tsx`, docsLayoutTemplate(cfg));
|
|
2259
2446
|
write("postcss.config.mjs", postcssConfigTemplate());
|
|
2260
2447
|
if (!fileExists(path.join(cwd, "tsconfig.json"))) write("tsconfig.json", tsconfigTemplate(cfg.useAlias));
|
|
2448
|
+
if (cfg.i18n?.locales.length) {
|
|
2449
|
+
write(`${appDir}/components/locale-doc-page.tsx`, nextLocaleDocPageTemplate(cfg.i18n.defaultLocale));
|
|
2450
|
+
write(`${appDir}/${cfg.entry}/page.tsx`, nextLocalizedPageTemplate({
|
|
2451
|
+
locales: cfg.i18n.locales,
|
|
2452
|
+
defaultLocale: cfg.i18n.defaultLocale,
|
|
2453
|
+
componentName: "DocsIndexPage",
|
|
2454
|
+
helperImport: "../components/locale-doc-page",
|
|
2455
|
+
pageImports: cfg.i18n.locales.map((locale) => ({
|
|
2456
|
+
locale,
|
|
2457
|
+
importPath: `./${locale}/page.mdx`
|
|
2458
|
+
}))
|
|
2459
|
+
}));
|
|
2460
|
+
write(`${appDir}/${cfg.entry}/installation/page.tsx`, nextLocalizedPageTemplate({
|
|
2461
|
+
locales: cfg.i18n.locales,
|
|
2462
|
+
defaultLocale: cfg.i18n.defaultLocale,
|
|
2463
|
+
componentName: "InstallationPage",
|
|
2464
|
+
helperImport: "../../components/locale-doc-page",
|
|
2465
|
+
pageImports: cfg.i18n.locales.map((locale) => ({
|
|
2466
|
+
locale,
|
|
2467
|
+
importPath: `../${locale}/installation/page.mdx`
|
|
2468
|
+
}))
|
|
2469
|
+
}));
|
|
2470
|
+
write(`${appDir}/${cfg.entry}/quickstart/page.tsx`, nextLocalizedPageTemplate({
|
|
2471
|
+
locales: cfg.i18n.locales,
|
|
2472
|
+
defaultLocale: cfg.i18n.defaultLocale,
|
|
2473
|
+
componentName: "QuickstartPage",
|
|
2474
|
+
helperImport: "../../components/locale-doc-page",
|
|
2475
|
+
pageImports: cfg.i18n.locales.map((locale) => ({
|
|
2476
|
+
locale,
|
|
2477
|
+
importPath: `../${locale}/quickstart/page.mdx`
|
|
2478
|
+
}))
|
|
2479
|
+
}));
|
|
2480
|
+
for (const locale of cfg.i18n.locales) {
|
|
2481
|
+
const base = `${appDir}/${cfg.entry}/${locale}`;
|
|
2482
|
+
write(`${base}/page.mdx`, welcomePageTemplate(cfg));
|
|
2483
|
+
write(`${base}/installation/page.mdx`, installationPageTemplate(cfg));
|
|
2484
|
+
write(`${base}/quickstart/page.mdx`, quickstartPageTemplate(cfg));
|
|
2485
|
+
}
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2261
2488
|
write(`${appDir}/${cfg.entry}/page.mdx`, welcomePageTemplate(cfg));
|
|
2262
2489
|
write(`${appDir}/${cfg.entry}/installation/page.mdx`, installationPageTemplate(cfg));
|
|
2263
2490
|
write(`${appDir}/${cfg.entry}/quickstart/page.mdx`, quickstartPageTemplate(cfg));
|
|
@@ -2273,6 +2500,7 @@ function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written)
|
|
|
2273
2500
|
write(`src/routes/${cfg.entry}/+layout.svelte`, svelteDocsLayoutTemplate(cfg));
|
|
2274
2501
|
write(`src/routes/${cfg.entry}/+layout.server.js`, svelteDocsLayoutServerTemplate(cfg));
|
|
2275
2502
|
write(`src/routes/${cfg.entry}/[...slug]/+page.svelte`, svelteDocsPageTemplate(cfg));
|
|
2503
|
+
if (cfg.i18n?.locales.length) write(`src/routes/${cfg.entry}/+page.svelte`, svelteDocsPageTemplate(cfg));
|
|
2276
2504
|
if (!readFileSafe(path.join(cwd, "src/routes/+layout.svelte"))) write("src/routes/+layout.svelte", svelteRootLayoutTemplate(globalCssRelPath));
|
|
2277
2505
|
const globalCssAbsPath = path.join(cwd, globalCssRelPath);
|
|
2278
2506
|
const existingGlobalCss = readFileSafe(globalCssAbsPath);
|
|
@@ -2293,9 +2521,11 @@ function scaffoldSvelteKit(cwd, cfg, globalCssRelPath, write, skipped, written)
|
|
|
2293
2521
|
written.push(globalCssRelPath + " (updated)");
|
|
2294
2522
|
} else skipped.push(globalCssRelPath + " (already configured)");
|
|
2295
2523
|
} else write(globalCssRelPath, cfg.theme === "custom" && cfg.customThemeName ? svelteGlobalCssTemplate("custom", cfg.customThemeName, globalCssRelPath) : svelteGlobalCssTemplate(cssTheme));
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2524
|
+
for (const base of getScaffoldContentRoots(cfg)) {
|
|
2525
|
+
write(`${base}/page.md`, svelteWelcomePageTemplate(cfg));
|
|
2526
|
+
write(`${base}/installation/page.md`, svelteInstallationPageTemplate(cfg));
|
|
2527
|
+
write(`${base}/quickstart/page.md`, svelteQuickstartPageTemplate(cfg));
|
|
2528
|
+
}
|
|
2299
2529
|
}
|
|
2300
2530
|
function scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
2301
2531
|
if (cfg.theme === "custom" && cfg.customThemeName) {
|
|
@@ -2328,9 +2558,11 @@ function scaffoldAstro(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
2328
2558
|
written.push(globalCssRelPath + " (updated)");
|
|
2329
2559
|
} else skipped.push(globalCssRelPath + " (already configured)");
|
|
2330
2560
|
} else write(globalCssRelPath, cfg.theme === "custom" && cfg.customThemeName ? astroGlobalCssTemplate("custom", cfg.customThemeName, globalCssRelPath) : astroGlobalCssTemplate(cssTheme));
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2561
|
+
for (const base of getScaffoldContentRoots(cfg)) {
|
|
2562
|
+
write(`${base}/page.md`, astroWelcomePageTemplate(cfg));
|
|
2563
|
+
write(`${base}/installation/page.md`, astroInstallationPageTemplate(cfg));
|
|
2564
|
+
write(`${base}/quickstart/page.md`, astroQuickstartPageTemplate(cfg));
|
|
2565
|
+
}
|
|
2334
2566
|
}
|
|
2335
2567
|
function scaffoldNuxt(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
2336
2568
|
if (cfg.theme === "custom" && cfg.customThemeName) {
|
|
@@ -2365,9 +2597,11 @@ function scaffoldNuxt(cwd, cfg, globalCssRelPath, write, skipped, written) {
|
|
|
2365
2597
|
written.push(globalCssRelPath + " (updated)");
|
|
2366
2598
|
} else skipped.push(globalCssRelPath + " (already configured)");
|
|
2367
2599
|
} else write(globalCssRelPath, cfg.theme === "custom" && cfg.customThemeName ? nuxtGlobalCssTemplate("custom", cfg.customThemeName, globalCssRelPath) : nuxtGlobalCssTemplate(cssTheme));
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2600
|
+
for (const base of getScaffoldContentRoots(cfg)) {
|
|
2601
|
+
write(`${base}/page.md`, nuxtWelcomePageTemplate(cfg));
|
|
2602
|
+
write(`${base}/installation/page.md`, nuxtInstallationPageTemplate(cfg));
|
|
2603
|
+
write(`${base}/quickstart/page.md`, nuxtQuickstartPageTemplate(cfg));
|
|
2604
|
+
}
|
|
2371
2605
|
}
|
|
2372
2606
|
|
|
2373
2607
|
//#endregion
|
package/dist/index.d.mts
CHANGED
|
@@ -999,11 +999,23 @@ interface CodeBlockCopyData {
|
|
|
999
999
|
/** Language / syntax hint (e.g. "tsx", "bash"), if present */
|
|
1000
1000
|
language?: string;
|
|
1001
1001
|
}
|
|
1002
|
+
interface DocsI18nConfig {
|
|
1003
|
+
/** Supported locale identifiers (e.g. ["en", "fr"]). */
|
|
1004
|
+
locales: string[];
|
|
1005
|
+
/** Default locale when `?lang=` is missing or invalid. Defaults to first locale. */
|
|
1006
|
+
defaultLocale?: string;
|
|
1007
|
+
}
|
|
1002
1008
|
interface DocsConfig {
|
|
1003
1009
|
/** Entry folder for docs (e.g. "docs" → /docs) */
|
|
1004
1010
|
entry: string;
|
|
1005
1011
|
/** Path to the content directory. Defaults to `entry` value. */
|
|
1006
1012
|
contentDir?: string;
|
|
1013
|
+
/**
|
|
1014
|
+
* Internationalization (i18n) configuration.
|
|
1015
|
+
* When set, docs content is expected under `${contentDir}/{locale}` and
|
|
1016
|
+
* the active locale is selected by `?lang=<locale>` in the URL.
|
|
1017
|
+
*/
|
|
1018
|
+
i18n?: DocsI18nConfig;
|
|
1007
1019
|
/**
|
|
1008
1020
|
* Set to `true` when building for full static export (e.g. Cloudflare Pages).
|
|
1009
1021
|
* When using `output: 'export'` in Next.js, the `/api/docs` route is not generated.
|
|
@@ -1326,6 +1338,21 @@ declare function createTheme(baseTheme: DocsTheme): (overrides?: Partial<DocsThe
|
|
|
1326
1338
|
*/
|
|
1327
1339
|
declare function extendTheme(baseTheme: DocsTheme, extensions: Partial<DocsTheme>): DocsTheme;
|
|
1328
1340
|
//#endregion
|
|
1341
|
+
//#region src/i18n.d.ts
|
|
1342
|
+
interface ResolvedDocsI18n {
|
|
1343
|
+
locales: string[];
|
|
1344
|
+
defaultLocale: string;
|
|
1345
|
+
}
|
|
1346
|
+
interface DocsPathMatch {
|
|
1347
|
+
/** Slug path relative to the docs root (no leading slash). */
|
|
1348
|
+
slug: string;
|
|
1349
|
+
/** Entry path used for URLs (no locale segment). */
|
|
1350
|
+
entryPath: string;
|
|
1351
|
+
}
|
|
1352
|
+
declare function resolveDocsI18n(config?: DocsI18nConfig | null): ResolvedDocsI18n | null;
|
|
1353
|
+
declare function resolveDocsLocale(searchParams: URLSearchParams, i18n?: ResolvedDocsI18n | null): string | undefined;
|
|
1354
|
+
declare function resolveDocsPath(pathname: string, entry: string): DocsPathMatch;
|
|
1355
|
+
//#endregion
|
|
1329
1356
|
//#region src/metadata.d.ts
|
|
1330
1357
|
/**
|
|
1331
1358
|
* Resolve page title using metadata titleTemplate.
|
|
@@ -1350,4 +1377,4 @@ declare function buildPageOpenGraph(page: Pick<PageFrontmatter, "title" | "descr
|
|
|
1350
1377
|
*/
|
|
1351
1378
|
declare function buildPageTwitter(page: Pick<PageFrontmatter, "title" | "description" | "ogImage" | "openGraph" | "twitter">, ogConfig?: OGConfig, baseUrl?: string): PageTwitter | undefined;
|
|
1352
1379
|
//#endregion
|
|
1353
|
-
export { type AIConfig, type BreadcrumbConfig, type CodeBlockCopyData, type CopyMarkdownConfig, type DocsConfig, type DocsMetadata, type DocsNav, type DocsTheme, type FontStyle, type GithubConfig, type LastUpdatedConfig, type LlmsTxtConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type OpenGraphImage, type OrderingItem, type PageActionsConfig, type PageFrontmatter, type PageOpenGraph, type PageTwitter, type SidebarComponentProps, type SidebarConfig, type SidebarFolderNode, type SidebarNode, type SidebarPageNode, type SidebarTree, type ThemeToggleConfig, type TypographyConfig, type UIConfig, buildPageOpenGraph, buildPageTwitter, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
|
|
1380
|
+
export { type AIConfig, type BreadcrumbConfig, type CodeBlockCopyData, type CopyMarkdownConfig, type DocsConfig, type DocsI18nConfig, type DocsMetadata, type DocsNav, type DocsPathMatch, type DocsTheme, type FontStyle, type GithubConfig, type LastUpdatedConfig, type LlmsTxtConfig, type OGConfig, type OpenDocsConfig, type OpenDocsProvider, type OpenGraphImage, type OrderingItem, type PageActionsConfig, type PageFrontmatter, type PageOpenGraph, type PageTwitter, type ResolvedDocsI18n, type SidebarComponentProps, type SidebarConfig, type SidebarFolderNode, type SidebarNode, type SidebarPageNode, type SidebarTree, type ThemeToggleConfig, type TypographyConfig, type UIConfig, buildPageOpenGraph, buildPageTwitter, createTheme, deepMerge, defineDocs, extendTheme, resolveDocsI18n, resolveDocsLocale, resolveDocsPath, resolveOGImage, resolveTitle };
|
package/dist/index.mjs
CHANGED
|
@@ -6,6 +6,7 @@ function defineDocs(config) {
|
|
|
6
6
|
return {
|
|
7
7
|
entry: config.entry ?? "docs",
|
|
8
8
|
contentDir: config.contentDir,
|
|
9
|
+
i18n: config.i18n,
|
|
9
10
|
theme: config.theme,
|
|
10
11
|
nav: config.nav,
|
|
11
12
|
github: config.github,
|
|
@@ -99,6 +100,45 @@ function extendTheme(baseTheme, extensions) {
|
|
|
99
100
|
return deepMerge(baseTheme, extensions);
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/i18n.ts
|
|
105
|
+
function normalizeSegment(value) {
|
|
106
|
+
return value.replace(/^\/+|\/+$/g, "");
|
|
107
|
+
}
|
|
108
|
+
function splitSegments(value) {
|
|
109
|
+
const cleaned = normalizeSegment(value);
|
|
110
|
+
return cleaned ? cleaned.split("/").filter(Boolean) : [];
|
|
111
|
+
}
|
|
112
|
+
function resolveDocsI18n(config) {
|
|
113
|
+
if (!config || !Array.isArray(config.locales)) return null;
|
|
114
|
+
const locales = Array.from(new Set(config.locales.map((l) => l.trim()).filter(Boolean)));
|
|
115
|
+
if (locales.length === 0) return null;
|
|
116
|
+
return {
|
|
117
|
+
locales,
|
|
118
|
+
defaultLocale: config.defaultLocale && locales.includes(config.defaultLocale) ? config.defaultLocale : locales[0]
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function resolveDocsLocale(searchParams, i18n) {
|
|
122
|
+
if (!i18n) return void 0;
|
|
123
|
+
const raw = searchParams.get("lang") ?? searchParams.get("locale");
|
|
124
|
+
if (!raw) return void 0;
|
|
125
|
+
if (i18n.locales.includes(raw)) return raw;
|
|
126
|
+
return i18n.defaultLocale;
|
|
127
|
+
}
|
|
128
|
+
function resolveDocsPath(pathname, entry) {
|
|
129
|
+
const entryBase = normalizeSegment(entry || "docs") || "docs";
|
|
130
|
+
const entryParts = splitSegments(entryBase);
|
|
131
|
+
const pathParts = splitSegments(pathname);
|
|
132
|
+
let rest = pathParts;
|
|
133
|
+
if (entryParts.length > 0) {
|
|
134
|
+
if (pathParts.slice(0, entryParts.length).join("/") === entryParts.join("/")) rest = pathParts.slice(entryParts.length);
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
slug: rest.join("/"),
|
|
138
|
+
entryPath: entryBase
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
102
142
|
//#endregion
|
|
103
143
|
//#region src/metadata.ts
|
|
104
144
|
/**
|
|
@@ -180,4 +220,4 @@ function buildPageTwitter(page, ogConfig, baseUrl) {
|
|
|
180
220
|
}
|
|
181
221
|
|
|
182
222
|
//#endregion
|
|
183
|
-
export { buildPageOpenGraph, buildPageTwitter, createTheme, deepMerge, defineDocs, extendTheme, resolveOGImage, resolveTitle };
|
|
223
|
+
export { buildPageOpenGraph, buildPageTwitter, createTheme, deepMerge, defineDocs, extendTheme, resolveDocsI18n, resolveDocsLocale, resolveDocsPath, resolveOGImage, resolveTitle };
|