create-fumadocs-app 16.0.34 → 16.0.35
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/bin.js +3 -3
- package/dist/bin.js.map +1 -1
- package/dist/{constants-CReWPhck.js → constants-DkM_O5ux.js} +10 -20
- package/dist/constants-DkM_O5ux.js.map +1 -0
- package/dist/{index-CC4EFQ5p.d.ts → index-CulTgtuF.d.ts} +2 -2
- package/dist/{index-CC4EFQ5p.d.ts.map → index-CulTgtuF.d.ts.map} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/plugins/biome.d.ts +1 -1
- package/dist/plugins/biome.js +2 -2
- package/dist/plugins/biome.js.map +1 -1
- package/dist/plugins/eslint.d.ts +1 -1
- package/dist/plugins/eslint.js +3 -3
- package/dist/plugins/eslint.js.map +1 -1
- package/dist/plugins/next-use-src.d.ts +1 -1
- package/dist/plugins/next-use-src.js +3 -3
- package/dist/plugins/next-use-src.js.map +1 -1
- package/dist/plugins/orama-cloud.d.ts +1 -1
- package/dist/plugins/orama-cloud.js +2 -1
- package/dist/plugins/orama-cloud.js.map +1 -1
- package/dist/{src-DWqRvlfn.js → src-z4C6ZcL7.js} +2 -2
- package/dist/{src-DWqRvlfn.js.map → src-z4C6ZcL7.js.map} +1 -1
- package/package.json +2 -2
- package/template/+next+fuma-docs-mdx/package.json +1 -1
- package/template/+next+fuma-docs-mdx+static/README.md +45 -0
- package/template/+next+fuma-docs-mdx+static/app/(home)/layout.tsx +6 -0
- package/template/+next+fuma-docs-mdx+static/app/(home)/page.tsx +16 -0
- package/template/+next+fuma-docs-mdx+static/app/api/search/route.ts +9 -0
- package/template/+next+fuma-docs-mdx+static/app/docs/[[...slug]]/page.tsx +47 -0
- package/template/+next+fuma-docs-mdx+static/app/docs/layout.tsx +11 -0
- package/template/+next+fuma-docs-mdx+static/app/global.css +3 -0
- package/template/+next+fuma-docs-mdx+static/app/layout.tsx +17 -0
- package/template/+next+fuma-docs-mdx+static/app/llms-full.txt/route.ts +10 -0
- package/template/+next+fuma-docs-mdx+static/app/og/docs/[...slug]/route.tsx +27 -0
- package/template/+next+fuma-docs-mdx+static/components/provider.tsx +8 -0
- package/template/+next+fuma-docs-mdx+static/components/search.tsx +46 -0
- package/template/+next+fuma-docs-mdx+static/content/docs/index.mdx +13 -0
- package/template/+next+fuma-docs-mdx+static/content/docs/test.mdx +17 -0
- package/template/+next+fuma-docs-mdx+static/example.gitignore +26 -0
- package/template/+next+fuma-docs-mdx+static/lib/layout.shared.tsx +9 -0
- package/template/+next+fuma-docs-mdx+static/lib/source.ts +26 -0
- package/template/+next+fuma-docs-mdx+static/mdx-components.tsx +9 -0
- package/template/+next+fuma-docs-mdx+static/next.config.mjs +11 -0
- package/template/+next+fuma-docs-mdx+static/package.json +32 -0
- package/template/+next+fuma-docs-mdx+static/postcss.config.mjs +5 -0
- package/template/+next+fuma-docs-mdx+static/source.config.ts +22 -0
- package/template/+next+fuma-docs-mdx+static/tsconfig.json +36 -0
- package/template/react-router/package.json +1 -1
- package/template/react-router-spa/package.json +1 -1
- package/template/tanstack-start/package.json +3 -4
- package/template/tanstack-start/vite.config.ts +0 -4
- package/template/tanstack-start-spa/package.json +4 -4
- package/template/waku/package.json +3 -1
- package/template/waku/src/lib/source.ts +2 -0
- package/dist/constants-CReWPhck.js.map +0 -1
package/dist/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { n as getPackageManager, r as managers, t as create } from "./src-
|
|
3
|
-
import { i as templates, n as isCI } from "./constants-
|
|
2
|
+
import { n as getPackageManager, r as managers, t as create } from "./src-z4C6ZcL7.js";
|
|
3
|
+
import { i as templates, n as isCI } from "./constants-DkM_O5ux.js";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { cancel, confirm, group, intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
|
|
@@ -46,7 +46,7 @@ async function main() {
|
|
|
46
46
|
if (isCI) return "disabled";
|
|
47
47
|
return select({
|
|
48
48
|
message: "Configure linter?",
|
|
49
|
-
options: results.template
|
|
49
|
+
options: results.template?.startsWith("+next") ? [
|
|
50
50
|
{
|
|
51
51
|
value: "disabled",
|
|
52
52
|
label: "Disabled"
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","names":["plugins: TemplatePlugin[]"],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport {\n cancel,\n confirm,\n group,\n intro,\n isCancel,\n outro,\n select,\n spinner,\n text,\n} from '@clack/prompts';\nimport pc from 'picocolors';\nimport { getPackageManager, managers } from './auto-install';\nimport { create, type Template, type TemplatePlugin } from './index';\nimport { isCI, templates } from './constants';\nimport { Option, program } from '@commander-js/extra-typings';\n\nconst command = program\n .argument('[name]', 'the project name')\n .option('--src', '(Next.js only) enable `src/` directory')\n .option('--install', 'install packages automatically')\n .option('--no-git', 'disable auto Git repository initialization')\n .addOption(\n new Option(\n '--linter <name>',\n 'configure a linter/formatter, ESLint is currently Next.js only.',\n ).choices(['eslint', 'biome']),\n )\n .addOption(\n new Option('--search <name>', 'configure a search solution').choices(['orama', 'orama-cloud']),\n )\n .addOption(\n new Option('--template <name>', 'choose a template').choices(\n templates.map((item) => item.value),\n ),\n )\n .addOption(\n new Option('--pm <name>', 'choose a package manager')\n .choices(managers)\n .default(getPackageManager()),\n );\n\nasync function main(): Promise<void> {\n command.parse(process.argv);\n const defaultName = command.args[0];\n const config = command.opts();\n intro(pc.bgCyan(pc.bold('Create Fumadocs App')));\n\n const options = await group(\n {\n name: async () => {\n if (defaultName) return defaultName;\n if (isCI) return 'untitled';\n\n return text({\n message: 'Project name',\n placeholder: 'my-app',\n defaultValue: 'my-app',\n });\n },\n template: async () => {\n if (config.template) return config.template;\n if (isCI) return '+next+fuma-docs-mdx';\n\n return select<Template>({\n message: 'Choose a template',\n initialValue: '+next+fuma-docs-mdx',\n options: templates,\n });\n },\n src: async ({ results }: { results: { template?: Template } }) => {\n if (config.src !== undefined) return config.src;\n if (isCI || !results.template?.startsWith('+next')) return false;\n\n return confirm({\n message: 'Use `/src` directory?',\n initialValue: false,\n });\n },\n lint: async ({ results }: { results: { template?: Template } }) => {\n if (config.linter !== undefined) return config.linter;\n if (isCI) return 'disabled';\n\n return select({\n message: 'Configure linter?',\n options:\n results.template === '+next+fuma-docs-mdx'\n ? [\n {\n value: 'disabled',\n label: 'Disabled',\n },\n {\n value: 'eslint',\n label: 'ESLint',\n },\n {\n value: 'biome',\n label: 'Biome',\n },\n ]\n : [\n {\n value: 'disabled',\n label: 'Disabled',\n },\n {\n value: 'biome',\n label: 'Biome',\n },\n ],\n });\n },\n search: async () => {\n if (config.search !== undefined) return config.search;\n if (isCI) return 'orama';\n\n return select({\n message: 'Choose a search solution?',\n options: [\n {\n value: 'orama',\n label: 'Default',\n hint: 'local search powered by Orama, recommended',\n },\n {\n value: 'orama-cloud',\n label: 'Orama Cloud',\n hint: '3rd party search solution, signup needed',\n },\n ],\n });\n },\n installDeps: async () => {\n if (config.install !== undefined) return config.install;\n if (isCI) return false;\n\n return confirm({\n message: `Do you want to install packages automatically? (detected as ${config.pm})`,\n });\n },\n },\n {\n onCancel: () => {\n cancel('Installation Stopped.');\n process.exit(0);\n },\n },\n );\n\n const projectName = options.name.toLowerCase().replace(/\\s/, '-');\n if (!isCI) await checkDir(projectName);\n\n const info = spinner();\n info.start(`Generating Project`);\n const plugins: TemplatePlugin[] = [];\n\n if (options.src) {\n const { nextUseSrc } = await import('./plugins/next-use-src');\n plugins.push(nextUseSrc());\n }\n\n if (options.search === 'orama-cloud') {\n const { oramaCloud } = await import('./plugins/orama-cloud');\n plugins.push(oramaCloud());\n }\n\n if (options.lint === 'eslint') {\n const { eslint } = await import('./plugins/eslint');\n plugins.push(eslint());\n }\n\n if (options.lint === 'biome') {\n const { biome } = await import('./plugins/biome');\n plugins.push(biome());\n }\n\n await create({\n packageManager: config.pm,\n template: options.template,\n outputDir: projectName,\n installDeps: options.installDeps,\n initializeGit: config.git,\n plugins,\n log: (message) => {\n info.message(message);\n },\n });\n\n info.stop('Project Generated');\n\n outro(pc.bgGreen(pc.bold('Done')));\n\n console.log(pc.bold('\\nOpen the project'));\n console.log(pc.cyan(`cd ${projectName}`));\n\n console.log(pc.bold('\\nRun Development Server'));\n if (config.pm === 'npm' || config.pm === 'bun') {\n console.log(pc.cyan(`${config.pm} run dev`));\n } else {\n console.log(pc.cyan(`${config.pm} dev`));\n }\n console.log(pc.bold('\\nYou can now open the project and start writing documents'));\n\n process.exit(0);\n}\n\nasync function checkDir(outputDir: string) {\n const destDir = await fs.readdir(outputDir).catch(() => null);\n if (!destDir || destDir.length === 0) return;\n const del = await confirm({\n message: `directory ${outputDir} already exists, do you want to delete its files?`,\n });\n\n if (isCancel(del)) {\n cancel();\n process.exit(1);\n }\n\n if (!del) return;\n\n const info = spinner();\n info.start(`Deleting files in ${outputDir}`);\n\n await Promise.all(\n destDir.map((item) => {\n return fs.rm(path.join(outputDir, item), {\n recursive: true,\n force: true,\n });\n }),\n );\n\n info.stop(`Deleted files in ${outputDir}`);\n}\n\nmain().catch((e: unknown) => {\n console.error(e);\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bin.js","names":["plugins: TemplatePlugin[]"],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport {\n cancel,\n confirm,\n group,\n intro,\n isCancel,\n outro,\n select,\n spinner,\n text,\n} from '@clack/prompts';\nimport pc from 'picocolors';\nimport { getPackageManager, managers } from './auto-install';\nimport { create, type Template, type TemplatePlugin } from './index';\nimport { isCI, templates } from './constants';\nimport { Option, program } from '@commander-js/extra-typings';\n\nconst command = program\n .argument('[name]', 'the project name')\n .option('--src', '(Next.js only) enable `src/` directory')\n .option('--install', 'install packages automatically')\n .option('--no-git', 'disable auto Git repository initialization')\n .addOption(\n new Option(\n '--linter <name>',\n 'configure a linter/formatter, ESLint is currently Next.js only.',\n ).choices(['eslint', 'biome']),\n )\n .addOption(\n new Option('--search <name>', 'configure a search solution').choices(['orama', 'orama-cloud']),\n )\n .addOption(\n new Option('--template <name>', 'choose a template').choices(\n templates.map((item) => item.value),\n ),\n )\n .addOption(\n new Option('--pm <name>', 'choose a package manager')\n .choices(managers)\n .default(getPackageManager()),\n );\n\nasync function main(): Promise<void> {\n command.parse(process.argv);\n const defaultName = command.args[0];\n const config = command.opts();\n intro(pc.bgCyan(pc.bold('Create Fumadocs App')));\n\n const options = await group(\n {\n name: async () => {\n if (defaultName) return defaultName;\n if (isCI) return 'untitled';\n\n return text({\n message: 'Project name',\n placeholder: 'my-app',\n defaultValue: 'my-app',\n });\n },\n template: async () => {\n if (config.template) return config.template;\n if (isCI) return '+next+fuma-docs-mdx';\n\n return select<Template>({\n message: 'Choose a template',\n initialValue: '+next+fuma-docs-mdx',\n options: templates,\n });\n },\n src: async ({ results }: { results: { template?: Template } }) => {\n if (config.src !== undefined) return config.src;\n if (isCI || !results.template?.startsWith('+next')) return false;\n\n return confirm({\n message: 'Use `/src` directory?',\n initialValue: false,\n });\n },\n lint: async ({ results }: { results: { template?: Template } }) => {\n if (config.linter !== undefined) return config.linter;\n if (isCI) return 'disabled';\n\n return select({\n message: 'Configure linter?',\n options: results.template?.startsWith('+next')\n ? [\n {\n value: 'disabled',\n label: 'Disabled',\n },\n {\n value: 'eslint',\n label: 'ESLint',\n },\n {\n value: 'biome',\n label: 'Biome',\n },\n ]\n : [\n {\n value: 'disabled',\n label: 'Disabled',\n },\n {\n value: 'biome',\n label: 'Biome',\n },\n ],\n });\n },\n search: async () => {\n if (config.search !== undefined) return config.search;\n if (isCI) return 'orama';\n\n return select({\n message: 'Choose a search solution?',\n options: [\n {\n value: 'orama',\n label: 'Default',\n hint: 'local search powered by Orama, recommended',\n },\n {\n value: 'orama-cloud',\n label: 'Orama Cloud',\n hint: '3rd party search solution, signup needed',\n },\n ],\n });\n },\n installDeps: async () => {\n if (config.install !== undefined) return config.install;\n if (isCI) return false;\n\n return confirm({\n message: `Do you want to install packages automatically? (detected as ${config.pm})`,\n });\n },\n },\n {\n onCancel: () => {\n cancel('Installation Stopped.');\n process.exit(0);\n },\n },\n );\n\n const projectName = options.name.toLowerCase().replace(/\\s/, '-');\n if (!isCI) await checkDir(projectName);\n\n const info = spinner();\n info.start(`Generating Project`);\n const plugins: TemplatePlugin[] = [];\n\n if (options.src) {\n const { nextUseSrc } = await import('./plugins/next-use-src');\n plugins.push(nextUseSrc());\n }\n\n if (options.search === 'orama-cloud') {\n const { oramaCloud } = await import('./plugins/orama-cloud');\n plugins.push(oramaCloud());\n }\n\n if (options.lint === 'eslint') {\n const { eslint } = await import('./plugins/eslint');\n plugins.push(eslint());\n }\n\n if (options.lint === 'biome') {\n const { biome } = await import('./plugins/biome');\n plugins.push(biome());\n }\n\n await create({\n packageManager: config.pm,\n template: options.template,\n outputDir: projectName,\n installDeps: options.installDeps,\n initializeGit: config.git,\n plugins,\n log: (message) => {\n info.message(message);\n },\n });\n\n info.stop('Project Generated');\n\n outro(pc.bgGreen(pc.bold('Done')));\n\n console.log(pc.bold('\\nOpen the project'));\n console.log(pc.cyan(`cd ${projectName}`));\n\n console.log(pc.bold('\\nRun Development Server'));\n if (config.pm === 'npm' || config.pm === 'bun') {\n console.log(pc.cyan(`${config.pm} run dev`));\n } else {\n console.log(pc.cyan(`${config.pm} dev`));\n }\n console.log(pc.bold('\\nYou can now open the project and start writing documents'));\n\n process.exit(0);\n}\n\nasync function checkDir(outputDir: string) {\n const destDir = await fs.readdir(outputDir).catch(() => null);\n if (!destDir || destDir.length === 0) return;\n const del = await confirm({\n message: `directory ${outputDir} already exists, do you want to delete its files?`,\n });\n\n if (isCancel(del)) {\n cancel();\n process.exit(1);\n }\n\n if (!del) return;\n\n const info = spinner();\n info.start(`Deleting files in ${outputDir}`);\n\n await Promise.all(\n destDir.map((item) => {\n return fs.rm(path.join(outputDir, item), {\n recursive: true,\n force: true,\n });\n }),\n );\n\n info.stop(`Deleted files in ${outputDir}`);\n}\n\nmain().catch((e: unknown) => {\n console.error(e);\n process.exit(1);\n});\n"],"mappings":"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"}
|
|
@@ -74,25 +74,14 @@ function pick(obj, keys) {
|
|
|
74
74
|
//#region ../create-app-versions/package.json
|
|
75
75
|
var dependencies = {
|
|
76
76
|
"@biomejs/biome": "^2.3.10",
|
|
77
|
-
"@
|
|
77
|
+
"@fumadocs/ui": "workspace:*",
|
|
78
|
+
"@orama/core": "^1.2.16",
|
|
78
79
|
"eslint": "^9.39.2",
|
|
79
80
|
"fumadocs-core": "workspace:*",
|
|
80
81
|
"fumadocs-mdx": "workspace:*",
|
|
81
82
|
"fumadocs-ui": "workspace:*"
|
|
82
83
|
};
|
|
83
84
|
|
|
84
|
-
//#endregion
|
|
85
|
-
//#region ../core/package.json
|
|
86
|
-
var version$2 = "16.4.2";
|
|
87
|
-
|
|
88
|
-
//#endregion
|
|
89
|
-
//#region ../ui/package.json
|
|
90
|
-
var version$1 = "16.4.2";
|
|
91
|
-
|
|
92
|
-
//#endregion
|
|
93
|
-
//#region ../mdx/package.json
|
|
94
|
-
var version = "14.2.4";
|
|
95
|
-
|
|
96
85
|
//#endregion
|
|
97
86
|
//#region src/constants.ts
|
|
98
87
|
const sourceDir = fileURLToPath(new URL(`../`, import.meta.url).href);
|
|
@@ -105,6 +94,12 @@ const templates = [
|
|
|
105
94
|
appDir: "",
|
|
106
95
|
rootProviderPath: "app/layout.tsx"
|
|
107
96
|
},
|
|
97
|
+
{
|
|
98
|
+
value: "+next+fuma-docs-mdx+static",
|
|
99
|
+
label: "Next.js Static: Fumadocs MDX",
|
|
100
|
+
appDir: "",
|
|
101
|
+
rootProviderPath: "components/provider.tsx"
|
|
102
|
+
},
|
|
108
103
|
{
|
|
109
104
|
value: "waku",
|
|
110
105
|
label: "Waku: Fumadocs MDX",
|
|
@@ -138,13 +133,8 @@ const templates = [
|
|
|
138
133
|
rootProviderPath: "routes/__root.tsx"
|
|
139
134
|
}
|
|
140
135
|
];
|
|
141
|
-
const depVersions =
|
|
142
|
-
...dependencies,
|
|
143
|
-
"fumadocs-core": version$2,
|
|
144
|
-
"fumadocs-ui": version$1,
|
|
145
|
-
"fumadocs-mdx": version
|
|
146
|
-
};
|
|
136
|
+
const depVersions = dependencies;
|
|
147
137
|
|
|
148
138
|
//#endregion
|
|
149
139
|
export { copy as a, writeFile as c, templates as i, isCI as n, pick as o, sourceDir as r, tryGitInit as s, depVersions as t };
|
|
150
|
-
//# sourceMappingURL=constants-
|
|
140
|
+
//# sourceMappingURL=constants-DkM_O5ux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-DkM_O5ux.js","names":["result: Partial<T>","templates: TemplateInfo[]","versionPkg.dependencies"],"sources":["../src/utils.ts","../../create-app-versions/package.json","../src/constants.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path, { join } from 'node:path';\nimport { x } from 'tinyexec';\n\nexport async function writeFile(file: string, content: string) {\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(file, content);\n}\n\nexport async function copy(\n from: string,\n to: string,\n options: {\n rename?: (s: string) => string;\n filter?: (s: string) => boolean;\n filterDir?: (dir: string) => boolean;\n } = {},\n): Promise<void> {\n const { rename = (s) => s, filterDir = () => true, filter = () => true } = options;\n const stats = await fs.stat(from);\n\n if (stats.isDirectory() && filterDir(from)) {\n const files = await fs.readdir(from);\n\n await Promise.all(\n files.map((file) => copy(path.join(from, file), path.join(to, file), options)),\n );\n }\n\n if (stats.isFile() && filter(from)) {\n to = rename(to);\n await fs.mkdir(path.dirname(to), { recursive: true });\n await fs.copyFile(from, to);\n }\n}\n\nasync function isInGitRepository(cwd: string) {\n const { exitCode } = await x('git', ['rev-parse', '--is-inside-work-tree'], {\n nodeOptions: { cwd },\n });\n\n return exitCode === 0;\n}\n\nasync function isDefaultBranchSet(cwd: string) {\n const { exitCode } = await x('git', ['config', 'init.defaultBranch'], {\n nodeOptions: { cwd },\n });\n\n return exitCode === 0;\n}\n\n/*\nInitialize a Git repo on the project.\n\nBased on https://github.com/vercel/next.js/blob/canary/packages/create-next-app/helpers/git.ts\n*/\nexport async function tryGitInit(cwd: string): Promise<boolean> {\n const { exitCode } = await x('git', ['--version']);\n if (exitCode !== 0) return false;\n\n if (await isInGitRepository(cwd)) return false;\n\n try {\n await x('git', ['init'], {\n throwOnError: true,\n nodeOptions: { cwd },\n });\n\n if (!(await isDefaultBranchSet(cwd))) {\n await x('git', ['checkout', '-b', 'main'], {\n throwOnError: true,\n nodeOptions: {\n cwd,\n },\n });\n }\n\n await x('git', ['add', '-A'], {\n throwOnError: true,\n nodeOptions: {\n cwd,\n },\n });\n\n await x('git', ['commit', '-m', 'Initial commit from Create Fumadocs App'], {\n throwOnError: true,\n nodeOptions: {\n cwd,\n },\n });\n return true;\n } catch {\n await fs.rmdir(join(cwd, '.git'), { recursive: true }).catch(() => null);\n\n return false;\n }\n}\n\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n const result: Partial<T> = {};\n\n for (const key of keys) {\n if (key in obj) {\n result[key] = obj[key];\n }\n }\n\n return result as Pick<T, K>;\n}\n","","import { fileURLToPath } from 'node:url';\nimport versionPkg from '../../create-app-versions/package.json';\n\nexport const sourceDir = fileURLToPath(new URL(`../`, import.meta.url).href);\n\nexport const isCI = Boolean(process.env.CI);\n\nexport interface TemplateInfo {\n value:\n | '+next+fuma-docs-mdx'\n | 'waku'\n | 'react-router'\n | 'react-router-spa'\n | 'tanstack-start'\n | 'tanstack-start-spa'\n | '+next+fuma-docs-mdx+static';\n label: string;\n appDir: string;\n /**\n * path to root provider, relative to `appDir``\n */\n rootProviderPath: string;\n hint?: string;\n /**\n * rename files when copying from template\n */\n rename?: (name: string) => string;\n}\n\nexport const templates: TemplateInfo[] = [\n {\n value: '+next+fuma-docs-mdx',\n label: 'Next.js: Fumadocs MDX',\n hint: 'recommended',\n appDir: '',\n rootProviderPath: 'app/layout.tsx',\n },\n {\n value: '+next+fuma-docs-mdx+static',\n label: 'Next.js Static: Fumadocs MDX',\n appDir: '',\n rootProviderPath: 'components/provider.tsx',\n },\n {\n value: 'waku',\n label: 'Waku: Fumadocs MDX',\n appDir: 'src',\n rootProviderPath: 'components/provider.tsx',\n },\n {\n value: 'react-router',\n label: 'React Router: Fumadocs MDX (not RSC)',\n appDir: 'app',\n rootProviderPath: 'root.tsx',\n },\n {\n value: 'react-router-spa',\n label: 'React Router SPA: Fumadocs MDX (not RSC)',\n hint: 'SPA mode allows you to host the site statically, compatible with a CDN.',\n appDir: 'app',\n rootProviderPath: 'root.tsx',\n },\n {\n value: 'tanstack-start',\n label: 'Tanstack Start: Fumadocs MDX (not RSC)',\n appDir: 'src',\n rootProviderPath: 'routes/__root.tsx',\n },\n {\n value: 'tanstack-start-spa',\n label: 'Tanstack Start SPA: Fumadocs MDX (not RSC)',\n hint: 'SPA mode allows you to host the site statically, compatible with a CDN.',\n appDir: 'src',\n rootProviderPath: 'routes/__root.tsx',\n },\n];\n\nexport const depVersions = versionPkg.dependencies;\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ declare const managers: readonly ["npm", "yarn", "bun", "pnpm"];
|
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region src/constants.d.ts
|
|
6
6
|
interface TemplateInfo {
|
|
7
|
-
value: '+next+fuma-docs-mdx' | 'waku' | 'react-router' | 'react-router-spa' | 'tanstack-start' | 'tanstack-start-spa';
|
|
7
|
+
value: '+next+fuma-docs-mdx' | 'waku' | 'react-router' | 'react-router-spa' | 'tanstack-start' | 'tanstack-start-spa' | '+next+fuma-docs-mdx+static';
|
|
8
8
|
label: string;
|
|
9
9
|
appDir: string;
|
|
10
10
|
/**
|
|
@@ -64,4 +64,4 @@ interface TemplatePlugin {
|
|
|
64
64
|
declare function create(createOptions: Options): Promise<void>;
|
|
65
65
|
//#endregion
|
|
66
66
|
export { TemplatePluginContext as a, TemplatePlugin as i, PackageJsonType as n, create as o, Template as r, Options as t };
|
|
67
|
-
//# sourceMappingURL=index-
|
|
67
|
+
//# sourceMappingURL=index-CulTgtuF.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-CulTgtuF.d.ts","names":[],"sources":["../src/auto-install.ts","../src/constants.ts","../src/index.ts"],"sourcesContent":[],"mappings":";KAEY,cAAA,WAAyB;AAAzB,cAEC,QAFa,EAAA,SAAW,CAAA,KAAQ,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,CAAA;;;AAEhC,UCGI,YAAA,CDH8C;;;;ECG9C;;;;ECAL,IAAA,CAAA,EAAA,MAAQ;EACH;;;EAcL,MAAA,CAAA,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,MAAA;;;;AFlBC,KEGD,QAAA,GAAW,YFHwC,CAAA,OAAA,CAAA;UEI9C,OAAA;;YAEL;EDHK;;;;ACAjB;EACiB,cAAO,CAAA,EASL,cATK;EAEZ,WAAA,CAAA,EAAA,OAAA;EAOO,aAAA,CAAA,EAAA,OAAA;EAKP,GAAA,CAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EAAc,OAAA,CAAA,EAAd,cAAc,EAAA;AAG1B;AAcY,UAdK,qBAAA,CAcU;EAIf,QAAA,EAjBA,YAiBA;EACK,GAAA,EAAA,CAAA,OAAA,EAAA,MAAA,EAAA,GAAA,IAAA;EACG;;;EAGf,IAAA,EAAA,MAAS;EAAM;;;EAAW,MAAA,EAAA,MAAA;AAE/B;AAEe,KAbH,eAAA,GAaG;EAAL,IAAA,CAAA,EAAA,MAAA;EACA,OAAA,CAAA,EAAA,MAAA;EACc,OAAA,CAAA,EAAA,OAAA;EAAjB,OAAA,CAAA,EAXK,MAWL,CAAA,MAAA,EAAA,MAAA,CAAA;EAEG,YAAA,CAAA,EAZO,MAYP,CAAA,MAAA,EAAA,MAAA,CAAA;EACO,eAAA,CAAA,EAZG,MAYH,CAAA,MAAA,EAAA,MAAA,CAAA;CACO,GAZpB,MAYoB,CAAA,MAAA,EAAA,OAAA,CAAA;KAVnB,SAUE,CAAA,CAAA,CAAA,GAVa,CAUb,GAViB,OAUjB,CAVyB,CAUzB,CAAA;AACe,UATL,cAAA,CASK;EAA0B,QAAA,CAAA,EAAA,CAAA,IAAA,EAPtC,IAOsC,CAPjC,qBAOiC,EAAA,MAAA,CAAA,EAAA,IAAA,EANtC,YAMsC,EAAA,GALzC,SAKyC,CAAA,IAAA,GALxB,YAKwB,CAAA;EAC9B,WAAA,CAAA,EAAA,CAAA,IAAA,EAJR,qBAIQ,EAAA,WAAA,EAHD,eAGC,EAAA,GAFX,SAEW,CAAA,IAAA,GAFM,eAEN,CAAA;EAA2C,UAAA,CAAA,EAAA,CAAA,IAAA,EADvC,qBACuC,EAAA,GADb,SACa,CAAA,IAAA,CAAA;EAAS,MAAA,CAAA,EAAA,CAAA,IAAA,EAApD,qBAAoD,EAAA,OAAA,EAAA,MAAA,EAAA,GAAT,SAAS,CAAA,IAAA,GAAA,MAAA,CAAA;AAGtE;iBAAsB,MAAA,gBAAsB,UAAU"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as TemplatePluginContext, i as TemplatePlugin, n as PackageJsonType, o as create, r as Template, t as Options } from "./index-
|
|
1
|
+
import { a as TemplatePluginContext, i as TemplatePlugin, n as PackageJsonType, o as create, r as Template, t as Options } from "./index-CulTgtuF.js";
|
|
2
2
|
export { Options, PackageJsonType, Template, TemplatePlugin, TemplatePluginContext, create };
|
package/dist/index.js
CHANGED
package/dist/plugins/biome.d.ts
CHANGED
package/dist/plugins/biome.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as writeFile, o as pick, t as depVersions } from "../constants-
|
|
1
|
+
import { c as writeFile, o as pick, t as depVersions } from "../constants-DkM_O5ux.js";
|
|
2
2
|
import biome_base_default from "./biome.base.js";
|
|
3
3
|
import biome_next_default from "./biome.next.js";
|
|
4
4
|
import path from "node:path";
|
|
@@ -21,7 +21,7 @@ function biome() {
|
|
|
21
21
|
};
|
|
22
22
|
},
|
|
23
23
|
async afterWrite() {
|
|
24
|
-
const config = this.template.value
|
|
24
|
+
const config = this.template.value.startsWith("+next") ? biome_next_default : biome_base_default;
|
|
25
25
|
await writeFile(path.join(this.dest, "biome.json"), JSON.stringify(config, null, 2));
|
|
26
26
|
this.log("Configured Biome");
|
|
27
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"biome.js","names":["next","base"],"sources":["../../src/plugins/biome.ts"],"sourcesContent":["import { TemplatePlugin } from '@/index';\nimport { pick, writeFile } from '@/utils';\nimport path from 'node:path';\nimport { depVersions } from '@/constants';\nimport base from './biome.base.json';\nimport next from './biome.next.json';\n\nexport function biome(): TemplatePlugin {\n return {\n packageJson(packageJson) {\n return {\n ...packageJson,\n scripts: {\n ...packageJson.scripts,\n lint: 'biome check',\n format: 'biome format --write',\n },\n devDependencies: {\n ...packageJson.devDependencies,\n ...pick(depVersions, ['@biomejs/biome']),\n },\n };\n },\n async afterWrite() {\n const config = this.template.value
|
|
1
|
+
{"version":3,"file":"biome.js","names":["next","base"],"sources":["../../src/plugins/biome.ts"],"sourcesContent":["import { TemplatePlugin } from '@/index';\nimport { pick, writeFile } from '@/utils';\nimport path from 'node:path';\nimport { depVersions } from '@/constants';\nimport base from './biome.base.json';\nimport next from './biome.next.json';\n\nexport function biome(): TemplatePlugin {\n return {\n packageJson(packageJson) {\n return {\n ...packageJson,\n scripts: {\n ...packageJson.scripts,\n lint: 'biome check',\n format: 'biome format --write',\n },\n devDependencies: {\n ...packageJson.devDependencies,\n ...pick(depVersions, ['@biomejs/biome']),\n },\n };\n },\n async afterWrite() {\n const config = this.template.value.startsWith('+next') ? next : base;\n\n await writeFile(path.join(this.dest, 'biome.json'), JSON.stringify(config, null, 2));\n this.log('Configured Biome');\n },\n };\n}\n"],"mappings":";;;;;;AAOA,SAAgB,QAAwB;AACtC,QAAO;EACL,YAAY,aAAa;AACvB,UAAO;IACL,GAAG;IACH,SAAS;KACP,GAAG,YAAY;KACf,MAAM;KACN,QAAQ;KACT;IACD,iBAAiB;KACf,GAAG,YAAY;KACf,GAAG,KAAK,aAAa,CAAC,iBAAiB,CAAC;KACzC;IACF;;EAEH,MAAM,aAAa;GACjB,MAAM,SAAS,KAAK,SAAS,MAAM,WAAW,QAAQ,GAAGA,qBAAOC;AAEhE,SAAM,UAAU,KAAK,KAAK,KAAK,MAAM,aAAa,EAAE,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AACpF,QAAK,IAAI,mBAAmB;;EAE/B"}
|
package/dist/plugins/eslint.d.ts
CHANGED
package/dist/plugins/eslint.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as writeFile, o as pick, t as depVersions } from "../constants-
|
|
1
|
+
import { c as writeFile, o as pick, t as depVersions } from "../constants-DkM_O5ux.js";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
//#region src/plugins/eslint.ts
|
|
@@ -20,7 +20,7 @@ export default eslintConfig;`;
|
|
|
20
20
|
function eslint() {
|
|
21
21
|
return {
|
|
22
22
|
packageJson(packageJson) {
|
|
23
|
-
if (this.template.value
|
|
23
|
+
if (!this.template.value.startsWith("+next")) return;
|
|
24
24
|
return {
|
|
25
25
|
...packageJson,
|
|
26
26
|
scripts: {
|
|
@@ -35,7 +35,7 @@ function eslint() {
|
|
|
35
35
|
};
|
|
36
36
|
},
|
|
37
37
|
async afterWrite() {
|
|
38
|
-
if (this.template.value
|
|
38
|
+
if (!this.template.value.startsWith("+next")) return;
|
|
39
39
|
await writeFile(path.join(this.dest, "eslint.config.mjs"), config);
|
|
40
40
|
this.log("Configured ESLint");
|
|
41
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eslint.js","names":[],"sources":["../../src/plugins/eslint.ts"],"sourcesContent":["import { TemplatePlugin } from '@/index';\nimport { pick, writeFile } from '@/utils';\nimport path from 'node:path';\nimport { depVersions } from '@/constants';\n\nconst config = `import { defineConfig, globalIgnores } from 'eslint/config';\nimport nextVitals from 'eslint-config-next/core-web-vitals';\n\nconst eslintConfig = defineConfig([\n ...nextVitals,\n globalIgnores([\n '.next/**',\n 'out/**',\n 'build/**',\n 'next-env.d.ts',\n '.source/**',\n ]),\n]);\n\nexport default eslintConfig;`;\n\nexport function eslint(): TemplatePlugin {\n return {\n packageJson(packageJson) {\n if (this.template.value
|
|
1
|
+
{"version":3,"file":"eslint.js","names":[],"sources":["../../src/plugins/eslint.ts"],"sourcesContent":["import { TemplatePlugin } from '@/index';\nimport { pick, writeFile } from '@/utils';\nimport path from 'node:path';\nimport { depVersions } from '@/constants';\n\nconst config = `import { defineConfig, globalIgnores } from 'eslint/config';\nimport nextVitals from 'eslint-config-next/core-web-vitals';\n\nconst eslintConfig = defineConfig([\n ...nextVitals,\n globalIgnores([\n '.next/**',\n 'out/**',\n 'build/**',\n 'next-env.d.ts',\n '.source/**',\n ]),\n]);\n\nexport default eslintConfig;`;\n\nexport function eslint(): TemplatePlugin {\n return {\n packageJson(packageJson) {\n if (!this.template.value.startsWith('+next')) return;\n\n return {\n ...packageJson,\n scripts: {\n ...packageJson.scripts,\n lint: 'eslint',\n },\n devDependencies: {\n ...packageJson.devDependencies,\n 'eslint-config-next': packageJson.dependencies!.next,\n ...pick(depVersions, ['eslint']),\n },\n };\n },\n async afterWrite() {\n if (!this.template.value.startsWith('+next')) return;\n\n await writeFile(path.join(this.dest, 'eslint.config.mjs'), config);\n this.log('Configured ESLint');\n },\n };\n}\n"],"mappings":";;;;AAKA,MAAM,SAAS;;;;;;;;;;;;;;;AAgBf,SAAgB,SAAyB;AACvC,QAAO;EACL,YAAY,aAAa;AACvB,OAAI,CAAC,KAAK,SAAS,MAAM,WAAW,QAAQ,CAAE;AAE9C,UAAO;IACL,GAAG;IACH,SAAS;KACP,GAAG,YAAY;KACf,MAAM;KACP;IACD,iBAAiB;KACf,GAAG,YAAY;KACf,sBAAsB,YAAY,aAAc;KAChD,GAAG,KAAK,aAAa,CAAC,SAAS,CAAC;KACjC;IACF;;EAEH,MAAM,aAAa;AACjB,OAAI,CAAC,KAAK,SAAS,MAAM,WAAW,QAAQ,CAAE;AAE9C,SAAM,UAAU,KAAK,KAAK,KAAK,MAAM,oBAAoB,EAAE,OAAO;AAClE,QAAK,IAAI,oBAAoB;;EAEhC"}
|
|
@@ -8,18 +8,18 @@ import path from "node:path";
|
|
|
8
8
|
function nextUseSrc() {
|
|
9
9
|
return {
|
|
10
10
|
template(info) {
|
|
11
|
-
if (info.value
|
|
11
|
+
if (!info.value.startsWith("+next")) return;
|
|
12
12
|
return {
|
|
13
13
|
...info,
|
|
14
14
|
appDir: "src",
|
|
15
15
|
rename: (file) => {
|
|
16
|
-
if (path.basename(file) === "mdx-components.tsx" || isRelative(path.join(this.dest, "app"), file) || isRelative(path.join(this.dest, "lib"), file)) return path.join(this.dest, "src", path.relative(this.dest, file));
|
|
16
|
+
if (path.basename(file) === "mdx-components.tsx" || isRelative(path.join(this.dest, "app"), file) || isRelative(path.join(this.dest, "lib"), file) || isRelative(path.join(this.dest, "components"), file)) return path.join(this.dest, "src", path.relative(this.dest, file));
|
|
17
17
|
return file;
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
},
|
|
21
21
|
async afterWrite() {
|
|
22
|
-
if (this.template.value
|
|
22
|
+
if (!this.template.value.startsWith("+next")) return;
|
|
23
23
|
const tsconfigPath = path.join(this.dest, "tsconfig.json");
|
|
24
24
|
const content = (await fs.readFile(tsconfigPath)).toString();
|
|
25
25
|
const config = JSON.parse(content);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-use-src.js","names":[],"sources":["../../src/plugins/next-use-src.ts"],"sourcesContent":["import { TemplatePlugin } from '@/index';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\n\n/**\n * Use `src` for app directory\n */\nexport function nextUseSrc(): TemplatePlugin {\n return {\n template(info) {\n if (info.value
|
|
1
|
+
{"version":3,"file":"next-use-src.js","names":[],"sources":["../../src/plugins/next-use-src.ts"],"sourcesContent":["import { TemplatePlugin } from '@/index';\nimport path from 'node:path';\nimport fs from 'node:fs/promises';\n\n/**\n * Use `src` for app directory\n */\nexport function nextUseSrc(): TemplatePlugin {\n return {\n template(info) {\n if (!info.value.startsWith('+next')) return;\n\n return {\n ...info,\n appDir: 'src',\n rename: (file) => {\n if (\n path.basename(file) === 'mdx-components.tsx' ||\n isRelative(path.join(this.dest, 'app'), file) ||\n isRelative(path.join(this.dest, 'lib'), file) ||\n isRelative(path.join(this.dest, 'components'), file)\n ) {\n return path.join(this.dest, 'src', path.relative(this.dest, file));\n }\n\n return file;\n },\n };\n },\n // update tsconfig.json for src dir\n async afterWrite() {\n if (!this.template.value.startsWith('+next')) return;\n\n const tsconfigPath = path.join(this.dest, 'tsconfig.json');\n const content = (await fs.readFile(tsconfigPath)).toString();\n const config = JSON.parse(content);\n\n if (config.compilerOptions?.paths) {\n Object.assign(config.compilerOptions.paths, {\n '@/*': ['./src/*'],\n });\n }\n\n await fs.writeFile(tsconfigPath, JSON.stringify(config, null, 2));\n },\n };\n}\n\nfunction isRelative(dir: string, file: string) {\n return !path.relative(dir, file).startsWith(`..${path.sep}`);\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,aAA6B;AAC3C,QAAO;EACL,SAAS,MAAM;AACb,OAAI,CAAC,KAAK,MAAM,WAAW,QAAQ,CAAE;AAErC,UAAO;IACL,GAAG;IACH,QAAQ;IACR,SAAS,SAAS;AAChB,SACE,KAAK,SAAS,KAAK,KAAK,wBACxB,WAAW,KAAK,KAAK,KAAK,MAAM,MAAM,EAAE,KAAK,IAC7C,WAAW,KAAK,KAAK,KAAK,MAAM,MAAM,EAAE,KAAK,IAC7C,WAAW,KAAK,KAAK,KAAK,MAAM,aAAa,EAAE,KAAK,CAEpD,QAAO,KAAK,KAAK,KAAK,MAAM,OAAO,KAAK,SAAS,KAAK,MAAM,KAAK,CAAC;AAGpE,YAAO;;IAEV;;EAGH,MAAM,aAAa;AACjB,OAAI,CAAC,KAAK,SAAS,MAAM,WAAW,QAAQ,CAAE;GAE9C,MAAM,eAAe,KAAK,KAAK,KAAK,MAAM,gBAAgB;GAC1D,MAAM,WAAW,MAAM,GAAG,SAAS,aAAa,EAAE,UAAU;GAC5D,MAAM,SAAS,KAAK,MAAM,QAAQ;AAElC,OAAI,OAAO,iBAAiB,MAC1B,QAAO,OAAO,OAAO,gBAAgB,OAAO,EAC1C,OAAO,CAAC,UAAU,EACnB,CAAC;AAGJ,SAAM,GAAG,UAAU,cAAc,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;;EAEpE;;AAGH,SAAS,WAAW,KAAa,MAAc;AAC7C,QAAO,CAAC,KAAK,SAAS,KAAK,KAAK,CAAC,WAAW,KAAK,KAAK,MAAM"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as copy, c as writeFile, o as pick, r as sourceDir, t as depVersions } from "../constants-
|
|
1
|
+
import { a as copy, c as writeFile, o as pick, r as sourceDir, t as depVersions } from "../constants-DkM_O5ux.js";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { IndentationText, Project, QuoteKind, StructureKind, SyntaxKind, ts } from "ts-morph";
|
|
@@ -222,6 +222,7 @@ See https://fumadocs.dev/docs/headless/search/orama-cloud for integrating Orama
|
|
|
222
222
|
else await Promise.all([fs.unlink(path.join(appDir, "pages/api/search.ts")).catch(() => null), writeFile(path.join(appDir, "pages/static.json.ts"), route.waku)]);
|
|
223
223
|
const filePath = {
|
|
224
224
|
"+next+fuma-docs-mdx": ".next/server/app/static.json.body",
|
|
225
|
+
"+next+fuma-docs-mdx+static": ".next/server/app/static.json.body",
|
|
225
226
|
"tanstack-start": ".output/public/static.json",
|
|
226
227
|
"tanstack-start-spa": "dist/client/static.json",
|
|
227
228
|
"react-router": "build/client/static.json",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orama-cloud.js","names":["path","SyntaxKind","path","path","tasks: Promise<unknown>[]"],"sources":["../../src/transform/shared.ts","../../src/transform/react-router.ts","../../src/transform/tanstack-start.ts","../../src/transform/index.ts","../../src/plugins/orama-cloud.ts"],"sourcesContent":["import { IndentationText, Project, QuoteKind } from 'ts-morph';\nimport fs from 'node:fs/promises';\n\nconst project = new Project({\n manipulationSettings: {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: QuoteKind.Single,\n },\n});\n\nexport async function createSourceFile(path: string) {\n return project.createSourceFile(path, (await fs.readFile(path)).toString(), {\n overwrite: true,\n });\n}\n\nexport function getCodeValue(v: string) {\n return new Function(`return ${v}`)();\n}\n","import { ArrayLiteralExpression, MethodDeclaration, SourceFile, ts } from 'ts-morph';\nimport { getCodeValue } from '@/transform/shared';\nimport SyntaxKind = ts.SyntaxKind;\n\n/**\n * filter items in a specific array initializer in the prerender function\n */\nexport function filterReactRouterPrerenderArray(\n sourceFile: SourceFile,\n array: 'paths' | 'excluded',\n filter: (item: string) => boolean,\n) {\n const methodBody = getPrerenderMethod(sourceFile)?.getBody();\n if (!methodBody) return;\n\n const initializer = methodBody\n .getDescendantsOfKind(SyntaxKind.VariableDeclaration)\n .find((item) => item.getName() === array)\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression);\n\n if (!initializer) return;\n for (const element of initializer.getElements()) {\n if (!filter(getCodeValue(element.getText()))) {\n initializer.removeElement(element);\n }\n }\n}\n\n/**\n * Add a new route to route config\n */\nexport function addReactRouterRoute(\n sourceFile: SourceFile,\n routes: { path: string; entry: string }[],\n) {\n modifyReactRouterRoutes(sourceFile, (arr) => {\n for (const { path, entry } of routes) {\n arr.addElement(`route('${path}', '${entry}')`);\n }\n });\n}\n\n/**\n * Remove routes from route config (root level only)\n */\nexport function filterReactRouterRoute(\n sourceFile: SourceFile,\n filter: (item: { path: string; entry: string }) => boolean,\n) {\n modifyReactRouterRoutes(sourceFile, (arr) => {\n for (const element of arr.getElements()) {\n if (\n !element.isKind(SyntaxKind.CallExpression) ||\n element.getFirstChildByKind(SyntaxKind.Identifier)?.getText() !== 'route'\n )\n continue;\n const args = element.getArguments();\n\n if (\n filter({\n path: getCodeValue(args[0].getText()),\n entry: getCodeValue(args[1].getText()),\n })\n )\n continue;\n\n arr.removeElement(element);\n }\n });\n}\n\nexport function modifyReactRouterRoutes(\n sourceFile: SourceFile,\n mod: (array: ArrayLiteralExpression) => void,\n) {\n const initializer = sourceFile\n .getDefaultExportSymbol()\n ?.getValueDeclaration()\n ?.getFirstDescendantByKind(SyntaxKind.ArrayLiteralExpression);\n if (initializer) mod(initializer);\n}\n\n/**\n * Find the prerender method from the config\n */\nfunction getPrerenderMethod(sourceFile: SourceFile): MethodDeclaration | null {\n return (\n sourceFile\n .getDefaultExportSymbol()\n ?.getValueDeclaration()\n ?.getFirstDescendantByKind(SyntaxKind.ObjectLiteralExpression)\n ?.getProperty('prerender')\n ?.asKind(SyntaxKind.MethodDeclaration) ?? null\n );\n}\n","import { CallExpression, SourceFile, SyntaxKind } from 'ts-morph';\nimport { getCodeValue } from '@/transform/shared';\n\n/**\n * Add path to the `pages` array in tanstack start vite config.\n *\n * If the `pages` property doesn't exist, create one.\n */\nexport function addTanstackPrerender(sourceFile: SourceFile, paths: string[]) {\n const optionsArg = getTanstackStartCall(sourceFile)\n ?.getArguments()[0]\n ?.asKind(SyntaxKind.ObjectLiteralExpression);\n if (!optionsArg) {\n return;\n }\n\n const pagesProperty = optionsArg.getProperty('pages')?.asKind(SyntaxKind.PropertyAssignment);\n\n function toItem(path: string) {\n return `{ path: '${path}' }`;\n }\n\n if (pagesProperty) {\n const initializer = pagesProperty.getInitializerIfKindOrThrow(\n SyntaxKind.ArrayLiteralExpression,\n );\n\n const existingPaths = new Set<string>();\n for (const element of initializer.getElements()) {\n const value = element\n .asKind(SyntaxKind.ObjectLiteralExpression)\n ?.getProperty('path')\n ?.asKind(SyntaxKind.PropertyAssignment)\n ?.getInitializer()\n ?.getText();\n\n if (value) {\n existingPaths.add(getCodeValue(value));\n }\n }\n\n for (const path of paths) {\n if (existingPaths.has(path)) continue;\n initializer.addElement(toItem(path));\n }\n } else {\n optionsArg.addProperty(`pages: [\\n${paths.map((path) => ` ${toItem(path)}`).join(',\\n')}\\n]`);\n }\n}\n\n/**\n * Find the tanstackStart call expression\n */\nfunction getTanstackStartCall(sourceFile: SourceFile): CallExpression | undefined {\n const pluginsProperty = sourceFile\n .getDefaultExportSymbol()\n ?.getValueDeclaration()\n ?.getFirstDescendantByKind(SyntaxKind.ObjectLiteralExpression)\n ?.getProperty('plugins')\n ?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression);\n\n if (!pluginsProperty) return;\n\n for (const element of pluginsProperty.getElements()) {\n const expression = element.asKind(SyntaxKind.CallExpression);\n if (expression?.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'tanstackStart') {\n return expression;\n }\n }\n}\n","import { TemplatePluginContext } from '@/index';\nimport { createSourceFile } from '@/transform/shared';\nimport path from 'node:path';\nimport {\n addReactRouterRoute,\n filterReactRouterPrerenderArray,\n filterReactRouterRoute,\n} from '@/transform/react-router';\nimport fs from 'node:fs/promises';\nimport { addTanstackPrerender } from '@/transform/tanstack-start';\nimport { StructureKind, SyntaxKind } from 'ts-morph';\n\ninterface RootLayoutMod {\n addSearchDialog: (specifier: string) => void;\n}\n\nexport async function rootProvider(\n { appDir, template }: TemplatePluginContext,\n fn: (mod: RootLayoutMod) => void,\n) {\n const file = await createSourceFile(path.join(appDir, template.rootProviderPath));\n fn({\n addSearchDialog(specifier) {\n const elements = file.getDescendantsOfKind(SyntaxKind.JsxElement);\n\n for (const element of elements) {\n const provider = element.getFirstChildByKind(SyntaxKind.JsxOpeningElement);\n if (provider?.getTagNameNode().getText() !== 'RootProvider') continue;\n\n // Skip if search prop already exists\n if (\n provider\n .getAttributes()\n .some(\n (attr) =>\n attr.isKind(SyntaxKind.JsxAttribute) && attr.getNameNode().getText() === 'search',\n )\n )\n continue;\n\n provider.addAttribute({\n kind: StructureKind.JsxAttribute,\n name: 'search',\n initializer: '{{ SearchDialog }}',\n });\n file.addImportDeclaration({\n moduleSpecifier: specifier,\n defaultImport: 'SearchDialog',\n });\n break;\n }\n },\n });\n await file.save();\n}\n\ninterface ReactRouterRoutesMod {\n /**\n * @param path API route's path\n * @param entry route's file path\n * @param code create the file if specified\n */\n addRoute: (path: string, entry: string, code?: string) => void;\n\n /**\n * @param path API route's path\n */\n removeRoute: (path: string) => void;\n}\n\nexport async function reactRouterRoutes(\n { dest, appDir }: TemplatePluginContext,\n fn: (mod: ReactRouterRoutesMod) => void,\n) {\n const configFile = await createSourceFile(path.join(dest, 'react-router.config.ts'));\n const routesFile = await createSourceFile(path.join(appDir, 'routes.ts'));\n const tasks: Promise<unknown>[] = [];\n\n function normalizePath(v: string) {\n return v.split('/').filter(Boolean).join('/');\n }\n\n fn({\n addRoute: (p, entry, code) => {\n addReactRouterRoute(routesFile, [{ path: p, entry }]);\n\n if (code) {\n tasks.push(fs.writeFile(path.join(appDir, entry), code));\n }\n },\n removeRoute: (p) => {\n const normalizedPath = normalizePath(p);\n\n filterReactRouterRoute(routesFile, (item) => {\n if (normalizePath(item.path) !== normalizedPath) return true;\n\n tasks.push(fs.unlink(path.join(appDir, item.entry)).catch(() => null));\n return false;\n });\n\n filterReactRouterPrerenderArray(\n configFile,\n 'excluded',\n (item) => normalizePath(item) !== normalizedPath,\n );\n\n filterReactRouterPrerenderArray(\n configFile,\n 'paths',\n (item) => normalizePath(item) !== normalizedPath,\n );\n },\n });\n\n await Promise.all([...tasks, routesFile.save(), configFile.save()]);\n}\n\nexport interface TanstackStartRoutesMod {\n addRoute: (options: {\n /**\n * file path relative to `routes`\n */\n path: string;\n\n /**\n * Generated route path of `path`\n */\n route: string;\n\n /**\n * if specified, create the file\n */\n code?: string;\n\n /**\n * if true, add to prerender list\n */\n prerender?: boolean;\n }) => void;\n\n removeRoute: (options: {\n /**\n * file path relative to routes directory\n */\n path: string;\n\n route: string;\n }) => void;\n}\n\nexport async function tanstackStartRoutes(\n { appDir, dest }: TemplatePluginContext,\n fn: (mod: TanstackStartRoutesMod) => void,\n) {\n const configFile = await createSourceFile(path.join(dest, 'vite.config.ts'));\n const tasks: Promise<unknown>[] = [];\n\n fn({\n addRoute(options) {\n if (options.code) {\n tasks.push(fs.writeFile(path.join(appDir, 'routes', options.path), options.code));\n }\n\n if (options.prerender) {\n addTanstackPrerender(configFile, [options.route]);\n }\n },\n removeRoute(options) {\n tasks.push(fs.unlink(path.join(appDir, 'routes', options.path)).catch(() => null));\n },\n });\n\n await Promise.all([...tasks, configFile.save()]);\n}\n","import { TemplatePlugin } from '@/index';\nimport { copy, pick, writeFile } from '@/utils';\nimport path from 'node:path';\nimport { depVersions, sourceDir } from '@/constants';\nimport fs from 'node:fs/promises';\nimport { reactRouterRoutes, rootProvider, tanstackStartRoutes } from '@/transform';\n\nexport function oramaCloud(): TemplatePlugin {\n return {\n packageJson(packageJson) {\n return {\n ...packageJson,\n scripts: {\n ...packageJson.scripts,\n build: `${packageJson.scripts!.build} && bun scripts/sync-content.ts`,\n },\n dependencies: {\n ...packageJson.dependencies,\n ...pick(depVersions, ['@orama/core']),\n },\n };\n },\n readme(content) {\n return `${content}\\n\\n## Orama Cloud\n \nThis project uses Orama Cloud for 3rd party search solution.\n\nSee https://fumadocs.dev/docs/headless/search/orama-cloud for integrating Orama Cloud to Fumadocs.`;\n },\n async afterWrite() {\n const { dest, appDir, template } = this;\n await copy(path.join(sourceDir, 'template/+orama-cloud/@root'), dest);\n await copy(path.join(sourceDir, 'template/+orama-cloud/@app'), appDir);\n\n await rootProvider(this, (mod) => mod.addSearchDialog('@/components/search'));\n\n if (template.value === 'tanstack-start') {\n await tanstackStartRoutes(this, (mod) => {\n mod.addRoute({\n path: 'static[.]json.ts',\n route: '/static.json',\n code: route.tanstack,\n prerender: true,\n });\n mod.removeRoute({\n path: 'api/search.ts',\n route: '/api/search',\n });\n });\n } else if (template.value.startsWith('react-router')) {\n await reactRouterRoutes(this, (mod) => {\n mod.addRoute('static.json', 'routes/static.ts', route['react-router']);\n mod.removeRoute('api/search');\n });\n } else if (template.value.startsWith('+next')) {\n await Promise.all([\n fs.unlink(path.join(appDir, 'app/api/search/route.ts')).catch(() => null),\n writeFile(path.join(appDir, 'app/static.json/route.ts'), route.next),\n ]);\n } else {\n await Promise.all([\n fs.unlink(path.join(appDir, 'pages/api/search.ts')).catch(() => null),\n writeFile(path.join(appDir, 'pages/static.json.ts'), route.waku),\n ]);\n }\n\n const filePath = {\n '+next+fuma-docs-mdx': '.next/server/app/static.json.body',\n 'tanstack-start': '.output/public/static.json',\n 'tanstack-start-spa': 'dist/client/static.json',\n 'react-router': 'build/client/static.json',\n 'react-router-spa': 'build/client/static.json',\n waku: 'dist/public/static.json',\n }[template.value];\n\n await writeFile(\n path.join(dest, 'scripts/sync-content.ts'),\n `import { type OramaDocument, sync } from 'fumadocs-core/search/orama-cloud';\nimport * as fs from 'node:fs/promises';\nimport { OramaCloud } from '@orama/core';\n\n// the path of pre-rendered \\`static.json\\`\nconst filePath = '${filePath}';\n\nasync function main() {\n const orama = new OramaCloud({\n projectId: process.env.NEXT_PUBLIC_ORAMA_PROJECT_ID,\n apiKey: process.env.ORAMA_PRIVATE_API_KEY,\n });\n\n const content = await fs.readFile(filePath);\n const records = JSON.parse(content.toString()) as OramaDocument[];\n\n await sync(orama, {\n index: process.env.NEXT_PUBLIC_ORAMA_DATASOURCE_ID,\n documents: records,\n });\n\n console.log(\\`search updated: \\${records.length} records\\`);\n}\n\nvoid main();`,\n );\n },\n };\n}\n\nconst route = {\n next: `import { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport const revalidate = false;\n\nexport async function GET() {\n return Response.json(await exportSearchIndexes());\n}`,\n 'react-router': `import { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport async function loader() {\n return Response.json(await exportSearchIndexes());\n}`,\n tanstack: `import { createFileRoute } from '@tanstack/react-router';\nimport { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport const Route = createFileRoute('/static.json')({\n server: {\n handlers: {\n GET: async () => Response.json(await exportSearchIndexes()),\n },\n },\n});`,\n waku: `import { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport async function GET() {\n return Response.json(await exportSearchIndexes());\n}\n\nexport const getConfig = () => ({\n render: 'static',\n});`,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"orama-cloud.js","names":["path","SyntaxKind","path","path","tasks: Promise<unknown>[]"],"sources":["../../src/transform/shared.ts","../../src/transform/react-router.ts","../../src/transform/tanstack-start.ts","../../src/transform/index.ts","../../src/plugins/orama-cloud.ts"],"sourcesContent":["import { IndentationText, Project, QuoteKind } from 'ts-morph';\nimport fs from 'node:fs/promises';\n\nconst project = new Project({\n manipulationSettings: {\n indentationText: IndentationText.TwoSpaces,\n quoteKind: QuoteKind.Single,\n },\n});\n\nexport async function createSourceFile(path: string) {\n return project.createSourceFile(path, (await fs.readFile(path)).toString(), {\n overwrite: true,\n });\n}\n\nexport function getCodeValue(v: string) {\n return new Function(`return ${v}`)();\n}\n","import { ArrayLiteralExpression, MethodDeclaration, SourceFile, ts } from 'ts-morph';\nimport { getCodeValue } from '@/transform/shared';\nimport SyntaxKind = ts.SyntaxKind;\n\n/**\n * filter items in a specific array initializer in the prerender function\n */\nexport function filterReactRouterPrerenderArray(\n sourceFile: SourceFile,\n array: 'paths' | 'excluded',\n filter: (item: string) => boolean,\n) {\n const methodBody = getPrerenderMethod(sourceFile)?.getBody();\n if (!methodBody) return;\n\n const initializer = methodBody\n .getDescendantsOfKind(SyntaxKind.VariableDeclaration)\n .find((item) => item.getName() === array)\n ?.getInitializerIfKind(SyntaxKind.ArrayLiteralExpression);\n\n if (!initializer) return;\n for (const element of initializer.getElements()) {\n if (!filter(getCodeValue(element.getText()))) {\n initializer.removeElement(element);\n }\n }\n}\n\n/**\n * Add a new route to route config\n */\nexport function addReactRouterRoute(\n sourceFile: SourceFile,\n routes: { path: string; entry: string }[],\n) {\n modifyReactRouterRoutes(sourceFile, (arr) => {\n for (const { path, entry } of routes) {\n arr.addElement(`route('${path}', '${entry}')`);\n }\n });\n}\n\n/**\n * Remove routes from route config (root level only)\n */\nexport function filterReactRouterRoute(\n sourceFile: SourceFile,\n filter: (item: { path: string; entry: string }) => boolean,\n) {\n modifyReactRouterRoutes(sourceFile, (arr) => {\n for (const element of arr.getElements()) {\n if (\n !element.isKind(SyntaxKind.CallExpression) ||\n element.getFirstChildByKind(SyntaxKind.Identifier)?.getText() !== 'route'\n )\n continue;\n const args = element.getArguments();\n\n if (\n filter({\n path: getCodeValue(args[0].getText()),\n entry: getCodeValue(args[1].getText()),\n })\n )\n continue;\n\n arr.removeElement(element);\n }\n });\n}\n\nexport function modifyReactRouterRoutes(\n sourceFile: SourceFile,\n mod: (array: ArrayLiteralExpression) => void,\n) {\n const initializer = sourceFile\n .getDefaultExportSymbol()\n ?.getValueDeclaration()\n ?.getFirstDescendantByKind(SyntaxKind.ArrayLiteralExpression);\n if (initializer) mod(initializer);\n}\n\n/**\n * Find the prerender method from the config\n */\nfunction getPrerenderMethod(sourceFile: SourceFile): MethodDeclaration | null {\n return (\n sourceFile\n .getDefaultExportSymbol()\n ?.getValueDeclaration()\n ?.getFirstDescendantByKind(SyntaxKind.ObjectLiteralExpression)\n ?.getProperty('prerender')\n ?.asKind(SyntaxKind.MethodDeclaration) ?? null\n );\n}\n","import { CallExpression, SourceFile, SyntaxKind } from 'ts-morph';\nimport { getCodeValue } from '@/transform/shared';\n\n/**\n * Add path to the `pages` array in tanstack start vite config.\n *\n * If the `pages` property doesn't exist, create one.\n */\nexport function addTanstackPrerender(sourceFile: SourceFile, paths: string[]) {\n const optionsArg = getTanstackStartCall(sourceFile)\n ?.getArguments()[0]\n ?.asKind(SyntaxKind.ObjectLiteralExpression);\n if (!optionsArg) {\n return;\n }\n\n const pagesProperty = optionsArg.getProperty('pages')?.asKind(SyntaxKind.PropertyAssignment);\n\n function toItem(path: string) {\n return `{ path: '${path}' }`;\n }\n\n if (pagesProperty) {\n const initializer = pagesProperty.getInitializerIfKindOrThrow(\n SyntaxKind.ArrayLiteralExpression,\n );\n\n const existingPaths = new Set<string>();\n for (const element of initializer.getElements()) {\n const value = element\n .asKind(SyntaxKind.ObjectLiteralExpression)\n ?.getProperty('path')\n ?.asKind(SyntaxKind.PropertyAssignment)\n ?.getInitializer()\n ?.getText();\n\n if (value) {\n existingPaths.add(getCodeValue(value));\n }\n }\n\n for (const path of paths) {\n if (existingPaths.has(path)) continue;\n initializer.addElement(toItem(path));\n }\n } else {\n optionsArg.addProperty(`pages: [\\n${paths.map((path) => ` ${toItem(path)}`).join(',\\n')}\\n]`);\n }\n}\n\n/**\n * Find the tanstackStart call expression\n */\nfunction getTanstackStartCall(sourceFile: SourceFile): CallExpression | undefined {\n const pluginsProperty = sourceFile\n .getDefaultExportSymbol()\n ?.getValueDeclaration()\n ?.getFirstDescendantByKind(SyntaxKind.ObjectLiteralExpression)\n ?.getProperty('plugins')\n ?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression);\n\n if (!pluginsProperty) return;\n\n for (const element of pluginsProperty.getElements()) {\n const expression = element.asKind(SyntaxKind.CallExpression);\n if (expression?.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'tanstackStart') {\n return expression;\n }\n }\n}\n","import { TemplatePluginContext } from '@/index';\nimport { createSourceFile } from '@/transform/shared';\nimport path from 'node:path';\nimport {\n addReactRouterRoute,\n filterReactRouterPrerenderArray,\n filterReactRouterRoute,\n} from '@/transform/react-router';\nimport fs from 'node:fs/promises';\nimport { addTanstackPrerender } from '@/transform/tanstack-start';\nimport { StructureKind, SyntaxKind } from 'ts-morph';\n\ninterface RootLayoutMod {\n addSearchDialog: (specifier: string) => void;\n}\n\nexport async function rootProvider(\n { appDir, template }: TemplatePluginContext,\n fn: (mod: RootLayoutMod) => void,\n) {\n const file = await createSourceFile(path.join(appDir, template.rootProviderPath));\n fn({\n addSearchDialog(specifier) {\n const elements = file.getDescendantsOfKind(SyntaxKind.JsxElement);\n\n for (const element of elements) {\n const provider = element.getFirstChildByKind(SyntaxKind.JsxOpeningElement);\n if (provider?.getTagNameNode().getText() !== 'RootProvider') continue;\n\n // Skip if search prop already exists\n if (\n provider\n .getAttributes()\n .some(\n (attr) =>\n attr.isKind(SyntaxKind.JsxAttribute) && attr.getNameNode().getText() === 'search',\n )\n )\n continue;\n\n provider.addAttribute({\n kind: StructureKind.JsxAttribute,\n name: 'search',\n initializer: '{{ SearchDialog }}',\n });\n file.addImportDeclaration({\n moduleSpecifier: specifier,\n defaultImport: 'SearchDialog',\n });\n break;\n }\n },\n });\n await file.save();\n}\n\ninterface ReactRouterRoutesMod {\n /**\n * @param path API route's path\n * @param entry route's file path\n * @param code create the file if specified\n */\n addRoute: (path: string, entry: string, code?: string) => void;\n\n /**\n * @param path API route's path\n */\n removeRoute: (path: string) => void;\n}\n\nexport async function reactRouterRoutes(\n { dest, appDir }: TemplatePluginContext,\n fn: (mod: ReactRouterRoutesMod) => void,\n) {\n const configFile = await createSourceFile(path.join(dest, 'react-router.config.ts'));\n const routesFile = await createSourceFile(path.join(appDir, 'routes.ts'));\n const tasks: Promise<unknown>[] = [];\n\n function normalizePath(v: string) {\n return v.split('/').filter(Boolean).join('/');\n }\n\n fn({\n addRoute: (p, entry, code) => {\n addReactRouterRoute(routesFile, [{ path: p, entry }]);\n\n if (code) {\n tasks.push(fs.writeFile(path.join(appDir, entry), code));\n }\n },\n removeRoute: (p) => {\n const normalizedPath = normalizePath(p);\n\n filterReactRouterRoute(routesFile, (item) => {\n if (normalizePath(item.path) !== normalizedPath) return true;\n\n tasks.push(fs.unlink(path.join(appDir, item.entry)).catch(() => null));\n return false;\n });\n\n filterReactRouterPrerenderArray(\n configFile,\n 'excluded',\n (item) => normalizePath(item) !== normalizedPath,\n );\n\n filterReactRouterPrerenderArray(\n configFile,\n 'paths',\n (item) => normalizePath(item) !== normalizedPath,\n );\n },\n });\n\n await Promise.all([...tasks, routesFile.save(), configFile.save()]);\n}\n\nexport interface TanstackStartRoutesMod {\n addRoute: (options: {\n /**\n * file path relative to `routes`\n */\n path: string;\n\n /**\n * Generated route path of `path`\n */\n route: string;\n\n /**\n * if specified, create the file\n */\n code?: string;\n\n /**\n * if true, add to prerender list\n */\n prerender?: boolean;\n }) => void;\n\n removeRoute: (options: {\n /**\n * file path relative to routes directory\n */\n path: string;\n\n route: string;\n }) => void;\n}\n\nexport async function tanstackStartRoutes(\n { appDir, dest }: TemplatePluginContext,\n fn: (mod: TanstackStartRoutesMod) => void,\n) {\n const configFile = await createSourceFile(path.join(dest, 'vite.config.ts'));\n const tasks: Promise<unknown>[] = [];\n\n fn({\n addRoute(options) {\n if (options.code) {\n tasks.push(fs.writeFile(path.join(appDir, 'routes', options.path), options.code));\n }\n\n if (options.prerender) {\n addTanstackPrerender(configFile, [options.route]);\n }\n },\n removeRoute(options) {\n tasks.push(fs.unlink(path.join(appDir, 'routes', options.path)).catch(() => null));\n },\n });\n\n await Promise.all([...tasks, configFile.save()]);\n}\n","import { TemplatePlugin } from '@/index';\nimport { copy, pick, writeFile } from '@/utils';\nimport path from 'node:path';\nimport { depVersions, sourceDir } from '@/constants';\nimport fs from 'node:fs/promises';\nimport { reactRouterRoutes, rootProvider, tanstackStartRoutes } from '@/transform';\n\nexport function oramaCloud(): TemplatePlugin {\n return {\n packageJson(packageJson) {\n return {\n ...packageJson,\n scripts: {\n ...packageJson.scripts,\n build: `${packageJson.scripts!.build} && bun scripts/sync-content.ts`,\n },\n dependencies: {\n ...packageJson.dependencies,\n ...pick(depVersions, ['@orama/core']),\n },\n };\n },\n readme(content) {\n return `${content}\\n\\n## Orama Cloud\n \nThis project uses Orama Cloud for 3rd party search solution.\n\nSee https://fumadocs.dev/docs/headless/search/orama-cloud for integrating Orama Cloud to Fumadocs.`;\n },\n async afterWrite() {\n const { dest, appDir, template } = this;\n await copy(path.join(sourceDir, 'template/+orama-cloud/@root'), dest);\n await copy(path.join(sourceDir, 'template/+orama-cloud/@app'), appDir);\n\n await rootProvider(this, (mod) => mod.addSearchDialog('@/components/search'));\n\n if (template.value === 'tanstack-start') {\n await tanstackStartRoutes(this, (mod) => {\n mod.addRoute({\n path: 'static[.]json.ts',\n route: '/static.json',\n code: route.tanstack,\n prerender: true,\n });\n mod.removeRoute({\n path: 'api/search.ts',\n route: '/api/search',\n });\n });\n } else if (template.value.startsWith('react-router')) {\n await reactRouterRoutes(this, (mod) => {\n mod.addRoute('static.json', 'routes/static.ts', route['react-router']);\n mod.removeRoute('api/search');\n });\n } else if (template.value.startsWith('+next')) {\n await Promise.all([\n fs.unlink(path.join(appDir, 'app/api/search/route.ts')).catch(() => null),\n writeFile(path.join(appDir, 'app/static.json/route.ts'), route.next),\n ]);\n } else {\n await Promise.all([\n fs.unlink(path.join(appDir, 'pages/api/search.ts')).catch(() => null),\n writeFile(path.join(appDir, 'pages/static.json.ts'), route.waku),\n ]);\n }\n\n const filePath = {\n '+next+fuma-docs-mdx': '.next/server/app/static.json.body',\n '+next+fuma-docs-mdx+static': '.next/server/app/static.json.body',\n 'tanstack-start': '.output/public/static.json',\n 'tanstack-start-spa': 'dist/client/static.json',\n 'react-router': 'build/client/static.json',\n 'react-router-spa': 'build/client/static.json',\n waku: 'dist/public/static.json',\n }[template.value];\n\n await writeFile(\n path.join(dest, 'scripts/sync-content.ts'),\n `import { type OramaDocument, sync } from 'fumadocs-core/search/orama-cloud';\nimport * as fs from 'node:fs/promises';\nimport { OramaCloud } from '@orama/core';\n\n// the path of pre-rendered \\`static.json\\`\nconst filePath = '${filePath}';\n\nasync function main() {\n const orama = new OramaCloud({\n projectId: process.env.NEXT_PUBLIC_ORAMA_PROJECT_ID,\n apiKey: process.env.ORAMA_PRIVATE_API_KEY,\n });\n\n const content = await fs.readFile(filePath);\n const records = JSON.parse(content.toString()) as OramaDocument[];\n\n await sync(orama, {\n index: process.env.NEXT_PUBLIC_ORAMA_DATASOURCE_ID,\n documents: records,\n });\n\n console.log(\\`search updated: \\${records.length} records\\`);\n}\n\nvoid main();`,\n );\n },\n };\n}\n\nconst route = {\n next: `import { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport const revalidate = false;\n\nexport async function GET() {\n return Response.json(await exportSearchIndexes());\n}`,\n 'react-router': `import { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport async function loader() {\n return Response.json(await exportSearchIndexes());\n}`,\n tanstack: `import { createFileRoute } from '@tanstack/react-router';\nimport { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport const Route = createFileRoute('/static.json')({\n server: {\n handlers: {\n GET: async () => Response.json(await exportSearchIndexes()),\n },\n },\n});`,\n waku: `import { exportSearchIndexes } from '@/lib/export-search-indexes';\n\nexport async function GET() {\n return Response.json(await exportSearchIndexes());\n}\n\nexport const getConfig = () => ({\n render: 'static',\n});`,\n};\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as copy, i as templates, r as sourceDir, s as tryGitInit, t as depVersions } from "./constants-
|
|
1
|
+
import { a as copy, i as templates, r as sourceDir, s as tryGitInit, t as depVersions } from "./constants-DkM_O5ux.js";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { x } from "tinyexec";
|
|
@@ -86,4 +86,4 @@ async function initPackageJson(projectName, packageJsonPath) {
|
|
|
86
86
|
|
|
87
87
|
//#endregion
|
|
88
88
|
export { getPackageManager as n, managers as r, create as t };
|
|
89
|
-
//# sourceMappingURL=src-
|
|
89
|
+
//# sourceMappingURL=src-z4C6ZcL7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"src-
|
|
1
|
+
{"version":3,"file":"src-z4C6ZcL7.js","names":["pluginContext: TemplatePluginContext","packageJson: PackageJsonType"],"sources":["../src/auto-install.ts","../src/index.ts"],"sourcesContent":["import { x } from 'tinyexec';\n\nexport type PackageManager = (typeof managers)[number];\n\nexport const managers = ['npm', 'yarn', 'bun', 'pnpm'] as const;\n\nexport function getPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent ?? '';\n\n if (userAgent.startsWith('yarn')) {\n return 'yarn';\n }\n\n if (userAgent.startsWith('pnpm')) {\n return 'pnpm';\n }\n\n if (userAgent.startsWith('bun')) {\n return 'bun';\n }\n\n return 'npm';\n}\n\nexport async function autoInstall(manager: PackageManager, dest: string) {\n await x(manager, ['install'], {\n throwOnError: true,\n nodeOptions: {\n env: {\n ...process.env,\n NODE_ENV: 'development',\n DISABLE_OPENCOLLECTIVE: '1',\n },\n cwd: dest,\n },\n });\n}\n","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { copy, tryGitInit } from '@/utils';\nimport type { PackageManager } from './auto-install';\nimport { autoInstall } from './auto-install';\nimport { depVersions, sourceDir, type TemplateInfo, templates } from './constants';\n\nexport type Template = TemplateInfo['value'];\nexport interface Options {\n outputDir: string;\n template: Template;\n\n /**\n * the package manager to use\n *\n * @defaultValue 'npm'\n */\n packageManager?: PackageManager;\n\n installDeps?: boolean;\n initializeGit?: boolean;\n log?: (message: string) => void;\n plugins?: TemplatePlugin[];\n}\n\nexport interface TemplatePluginContext {\n template: TemplateInfo;\n log: (message: string) => void;\n /**\n * output directory\n */\n dest: string;\n\n /**\n * output directory for app code (e.g. under `/src`)\n */\n appDir: string;\n}\n\nexport type PackageJsonType = {\n name?: string;\n version?: string;\n private?: boolean;\n scripts?: Record<string, string>;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n} & Record<string, unknown>;\n\ntype Awaitable<T> = T | Promise<T>;\n\nexport interface TemplatePlugin {\n template?: (\n this: Pick<TemplatePluginContext, 'dest'>,\n info: TemplateInfo,\n ) => Awaitable<void | TemplateInfo>;\n packageJson?: (\n this: TemplatePluginContext,\n packageJson: PackageJsonType,\n ) => Awaitable<void | PackageJsonType>;\n afterWrite?: (this: TemplatePluginContext) => Awaitable<void>;\n readme?: (this: TemplatePluginContext, content: string) => Awaitable<void | string>;\n}\n\nexport async function create(createOptions: Options): Promise<void> {\n const {\n outputDir,\n plugins = [],\n packageManager = 'npm',\n initializeGit = false,\n installDeps = false,\n log = console.log,\n } = createOptions;\n\n let template = templates.find((item) => item.value === createOptions.template)!;\n for (const plugin of plugins) {\n template = (await plugin.template?.call({ dest: outputDir }, template)) ?? template;\n }\n\n const appDir = path.join(outputDir, template.appDir);\n const projectName = path.basename(outputDir);\n const pluginContext: TemplatePluginContext = {\n template,\n dest: outputDir,\n log,\n appDir,\n };\n\n await copy(path.join(sourceDir, 'template', template.value), outputDir, {\n rename(file) {\n file = file.replace('example.gitignore', '.gitignore');\n\n return template.rename?.(file) ?? file;\n },\n });\n\n const packageJsonPath = path.join(outputDir, 'package.json');\n let packageJson = await initPackageJson(projectName, packageJsonPath);\n for (const plugin of plugins) {\n packageJson = (await plugin.packageJson?.call(pluginContext, packageJson)) ?? packageJson;\n }\n await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));\n\n const readmePath = path.join(outputDir, 'README.md');\n let readme = `# ${projectName}\\n\\n${await fs.readFile(readmePath)}`;\n for (const plugin of plugins) {\n readme = (await plugin.readme?.call(pluginContext, readme)) ?? readme;\n }\n await fs.writeFile(readmePath, readme);\n\n for (const plugin of plugins) {\n await plugin.afterWrite?.call(pluginContext);\n }\n\n if (installDeps) {\n try {\n await autoInstall(packageManager, outputDir);\n log('Installed dependencies');\n } catch (err) {\n log(`Failed to install dependencies: ${err}`);\n }\n }\n\n if (initializeGit && (await tryGitInit(outputDir))) {\n log('Initialized Git repository');\n }\n}\n\nasync function initPackageJson(\n projectName: string,\n packageJsonPath: string,\n): Promise<PackageJsonType> {\n function replaceWorkspaceDeps(deps: Record<string, string> = {}) {\n for (const k in deps) {\n if (deps[k].startsWith('workspace:') && k in depVersions) {\n deps[k] = depVersions[k as keyof typeof depVersions];\n }\n }\n\n return deps;\n }\n\n const packageJson: PackageJsonType = JSON.parse((await fs.readFile(packageJsonPath)).toString());\n\n return {\n ...packageJson,\n name: projectName,\n scripts: {\n ...packageJson.scripts,\n postinstall: 'fumadocs-mdx',\n },\n dependencies: replaceWorkspaceDeps(packageJson.dependencies),\n devDependencies: replaceWorkspaceDeps(packageJson.devDependencies),\n };\n}\n"],"mappings":";;;;;;AAIA,MAAa,WAAW;CAAC;CAAO;CAAQ;CAAO;CAAO;AAEtD,SAAgB,oBAAoC;CAClD,MAAM,YAAY,QAAQ,IAAI,yBAAyB;AAEvD,KAAI,UAAU,WAAW,OAAO,CAC9B,QAAO;AAGT,KAAI,UAAU,WAAW,OAAO,CAC9B,QAAO;AAGT,KAAI,UAAU,WAAW,MAAM,CAC7B,QAAO;AAGT,QAAO;;AAGT,eAAsB,YAAY,SAAyB,MAAc;AACvE,OAAM,EAAE,SAAS,CAAC,UAAU,EAAE;EAC5B,cAAc;EACd,aAAa;GACX,KAAK;IACH,GAAG,QAAQ;IACX,UAAU;IACV,wBAAwB;IACzB;GACD,KAAK;GACN;EACF,CAAC;;;;;AC4BJ,eAAsB,OAAO,eAAuC;CAClE,MAAM,EACJ,WACA,UAAU,EAAE,EACZ,iBAAiB,OACjB,gBAAgB,OAChB,cAAc,OACd,MAAM,QAAQ,QACZ;CAEJ,IAAI,WAAW,UAAU,MAAM,SAAS,KAAK,UAAU,cAAc,SAAS;AAC9E,MAAK,MAAM,UAAU,QACnB,YAAY,MAAM,OAAO,UAAU,KAAK,EAAE,MAAM,WAAW,EAAE,SAAS,IAAK;CAG7E,MAAM,SAAS,KAAK,KAAK,WAAW,SAAS,OAAO;CACpD,MAAM,cAAc,KAAK,SAAS,UAAU;CAC5C,MAAMA,gBAAuC;EAC3C;EACA,MAAM;EACN;EACA;EACD;AAED,OAAM,KAAK,KAAK,KAAK,WAAW,YAAY,SAAS,MAAM,EAAE,WAAW,EACtE,OAAO,MAAM;AACX,SAAO,KAAK,QAAQ,qBAAqB,aAAa;AAEtD,SAAO,SAAS,SAAS,KAAK,IAAI;IAErC,CAAC;CAEF,MAAM,kBAAkB,KAAK,KAAK,WAAW,eAAe;CAC5D,IAAI,cAAc,MAAM,gBAAgB,aAAa,gBAAgB;AACrE,MAAK,MAAM,UAAU,QACnB,eAAe,MAAM,OAAO,aAAa,KAAK,eAAe,YAAY,IAAK;AAEhF,OAAM,GAAG,UAAU,iBAAiB,KAAK,UAAU,aAAa,MAAM,EAAE,CAAC;CAEzE,MAAM,aAAa,KAAK,KAAK,WAAW,YAAY;CACpD,IAAI,SAAS,KAAK,YAAY,MAAM,MAAM,GAAG,SAAS,WAAW;AACjE,MAAK,MAAM,UAAU,QACnB,UAAU,MAAM,OAAO,QAAQ,KAAK,eAAe,OAAO,IAAK;AAEjE,OAAM,GAAG,UAAU,YAAY,OAAO;AAEtC,MAAK,MAAM,UAAU,QACnB,OAAM,OAAO,YAAY,KAAK,cAAc;AAG9C,KAAI,YACF,KAAI;AACF,QAAM,YAAY,gBAAgB,UAAU;AAC5C,MAAI,yBAAyB;UACtB,KAAK;AACZ,MAAI,mCAAmC,MAAM;;AAIjD,KAAI,iBAAkB,MAAM,WAAW,UAAU,CAC/C,KAAI,6BAA6B;;AAIrC,eAAe,gBACb,aACA,iBAC0B;CAC1B,SAAS,qBAAqB,OAA+B,EAAE,EAAE;AAC/D,OAAK,MAAM,KAAK,KACd,KAAI,KAAK,GAAG,WAAW,aAAa,IAAI,KAAK,YAC3C,MAAK,KAAK,YAAY;AAI1B,SAAO;;CAGT,MAAMC,cAA+B,KAAK,OAAO,MAAM,GAAG,SAAS,gBAAgB,EAAE,UAAU,CAAC;AAEhG,QAAO;EACL,GAAG;EACH,MAAM;EACN,SAAS;GACP,GAAG,YAAY;GACf,aAAa;GACd;EACD,cAAc,qBAAqB,YAAY,aAAa;EAC5D,iBAAiB,qBAAqB,YAAY,gBAAgB;EACnE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fumadocs-app",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.35",
|
|
4
4
|
"description": "Create a new documentation site with Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Docs",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@types/cross-spawn": "^6.0.6",
|
|
45
45
|
"@types/node": "24.10.2",
|
|
46
46
|
"tinyglobby": "^0.2.15",
|
|
47
|
-
"tsdown": "^0.18.
|
|
47
|
+
"tsdown": "^0.18.4",
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
49
|
"eslint-config-custom": "0.0.0",
|
|
50
50
|
"tsconfig": "0.0.0"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
This is a Next.js application generated with
|
|
2
|
+
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
|
|
3
|
+
|
|
4
|
+
It is a Next.js app with [Static Export](https://nextjs.org/docs/app/guides/static-exports) configured.
|
|
5
|
+
|
|
6
|
+
Run development server:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm run dev
|
|
10
|
+
# or
|
|
11
|
+
pnpm dev
|
|
12
|
+
# or
|
|
13
|
+
yarn dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Open http://localhost:3000 with your browser to see the result.
|
|
17
|
+
|
|
18
|
+
## Explore
|
|
19
|
+
|
|
20
|
+
In the project, you can see:
|
|
21
|
+
|
|
22
|
+
- `lib/source.ts`: Code for content source adapter, [`loader()`](https://fumadocs.dev/docs/headless/source-api) provides the interface to access your content.
|
|
23
|
+
- `lib/layout.shared.tsx`: Shared options for layouts, optional but preferred to keep.
|
|
24
|
+
|
|
25
|
+
| Route | Description |
|
|
26
|
+
| ------------------------- | ------------------------------------------------------ |
|
|
27
|
+
| `app/(home)` | The route group for your landing page and other pages. |
|
|
28
|
+
| `app/docs` | The documentation layout and pages. |
|
|
29
|
+
| `app/api/search/route.ts` | The Route Handler for search. |
|
|
30
|
+
|
|
31
|
+
### Fumadocs MDX
|
|
32
|
+
|
|
33
|
+
A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
|
|
34
|
+
|
|
35
|
+
Read the [Introduction](https://fumadocs.dev/docs/mdx) for further details.
|
|
36
|
+
|
|
37
|
+
## Learn More
|
|
38
|
+
|
|
39
|
+
To learn more about Next.js and Fumadocs, take a look at the following
|
|
40
|
+
resources:
|
|
41
|
+
|
|
42
|
+
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
|
|
43
|
+
features and API.
|
|
44
|
+
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
45
|
+
- [Fumadocs](https://fumadocs.dev) - learn about Fumadocs
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Link from 'next/link';
|
|
2
|
+
|
|
3
|
+
export default function HomePage() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="flex flex-col justify-center text-center flex-1">
|
|
6
|
+
<h1 className="text-2xl font-bold mb-4">Hello World</h1>
|
|
7
|
+
<p>
|
|
8
|
+
You can open{' '}
|
|
9
|
+
<Link href="/docs" className="font-medium underline">
|
|
10
|
+
/docs
|
|
11
|
+
</Link>{' '}
|
|
12
|
+
and see the documentation.
|
|
13
|
+
</p>
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { source } from '@/lib/source';
|
|
2
|
+
import { createFromSource } from 'fumadocs-core/search/server';
|
|
3
|
+
|
|
4
|
+
export const revalidate = false;
|
|
5
|
+
|
|
6
|
+
export const { staticGET: GET } = createFromSource(source, {
|
|
7
|
+
// https://docs.orama.com/docs/orama-js/supported-languages
|
|
8
|
+
language: 'english',
|
|
9
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getPageImage, source } from '@/lib/source';
|
|
2
|
+
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
|
|
3
|
+
import { notFound } from 'next/navigation';
|
|
4
|
+
import { getMDXComponents } from '@/mdx-components';
|
|
5
|
+
import type { Metadata } from 'next';
|
|
6
|
+
import { createRelativeLink } from 'fumadocs-ui/mdx';
|
|
7
|
+
|
|
8
|
+
export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
|
|
9
|
+
const params = await props.params;
|
|
10
|
+
const page = source.getPage(params.slug);
|
|
11
|
+
if (!page) notFound();
|
|
12
|
+
|
|
13
|
+
const MDX = page.data.body;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<DocsPage toc={page.data.toc} full={page.data.full}>
|
|
17
|
+
<DocsTitle>{page.data.title}</DocsTitle>
|
|
18
|
+
<DocsDescription>{page.data.description}</DocsDescription>
|
|
19
|
+
<DocsBody>
|
|
20
|
+
<MDX
|
|
21
|
+
components={getMDXComponents({
|
|
22
|
+
// this allows you to link to other pages with relative file paths
|
|
23
|
+
a: createRelativeLink(source, page),
|
|
24
|
+
})}
|
|
25
|
+
/>
|
|
26
|
+
</DocsBody>
|
|
27
|
+
</DocsPage>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function generateStaticParams() {
|
|
32
|
+
return source.generateParams();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function generateMetadata(props: PageProps<'/docs/[[...slug]]'>): Promise<Metadata> {
|
|
36
|
+
const params = await props.params;
|
|
37
|
+
const page = source.getPage(params.slug);
|
|
38
|
+
if (!page) notFound();
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
title: page.data.title,
|
|
42
|
+
description: page.data.description,
|
|
43
|
+
openGraph: {
|
|
44
|
+
images: getPageImage(page).url,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { source } from '@/lib/source';
|
|
2
|
+
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
|
3
|
+
import { baseOptions } from '@/lib/layout.shared';
|
|
4
|
+
|
|
5
|
+
export default function Layout({ children }: LayoutProps<'/docs'>) {
|
|
6
|
+
return (
|
|
7
|
+
<DocsLayout tree={source.getPageTree()} {...baseOptions()}>
|
|
8
|
+
{children}
|
|
9
|
+
</DocsLayout>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Inter } from 'next/font/google';
|
|
2
|
+
import { Provider } from '@/components/provider';
|
|
3
|
+
import './global.css';
|
|
4
|
+
|
|
5
|
+
const inter = Inter({
|
|
6
|
+
subsets: ['latin'],
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export default function Layout({ children }: LayoutProps<'/'>) {
|
|
10
|
+
return (
|
|
11
|
+
<html lang="en" className={inter.className} suppressHydrationWarning>
|
|
12
|
+
<body className="flex flex-col min-h-screen">
|
|
13
|
+
<Provider>{children}</Provider>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getLLMText, source } from '@/lib/source';
|
|
2
|
+
|
|
3
|
+
export const revalidate = false;
|
|
4
|
+
|
|
5
|
+
export async function GET() {
|
|
6
|
+
const scan = source.getPages().map(getLLMText);
|
|
7
|
+
const scanned = await Promise.all(scan);
|
|
8
|
+
|
|
9
|
+
return new Response(scanned.join('\n\n'));
|
|
10
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getPageImage, source } from '@/lib/source';
|
|
2
|
+
import { notFound } from 'next/navigation';
|
|
3
|
+
import { ImageResponse } from 'next/og';
|
|
4
|
+
import { generate as DefaultImage } from 'fumadocs-ui/og';
|
|
5
|
+
|
|
6
|
+
export const revalidate = false;
|
|
7
|
+
|
|
8
|
+
export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[...slug]'>) {
|
|
9
|
+
const { slug } = await params;
|
|
10
|
+
const page = source.getPage(slug.slice(0, -1));
|
|
11
|
+
if (!page) notFound();
|
|
12
|
+
|
|
13
|
+
return new ImageResponse(
|
|
14
|
+
<DefaultImage title={page.data.title} description={page.data.description} site="My App" />,
|
|
15
|
+
{
|
|
16
|
+
width: 1200,
|
|
17
|
+
height: 630,
|
|
18
|
+
},
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function generateStaticParams() {
|
|
23
|
+
return source.getPages().map((page) => ({
|
|
24
|
+
lang: page.locale,
|
|
25
|
+
slug: getPageImage(page).segments,
|
|
26
|
+
}));
|
|
27
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import SearchDialog from '@/components/search';
|
|
3
|
+
import { RootProvider } from 'fumadocs-ui/provider/next';
|
|
4
|
+
import { type ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
export function Provider({ children }: { children: ReactNode }) {
|
|
7
|
+
return <RootProvider search={{ SearchDialog }}>{children}</RootProvider>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
SearchDialog,
|
|
4
|
+
SearchDialogClose,
|
|
5
|
+
SearchDialogContent,
|
|
6
|
+
SearchDialogHeader,
|
|
7
|
+
SearchDialogIcon,
|
|
8
|
+
SearchDialogInput,
|
|
9
|
+
SearchDialogList,
|
|
10
|
+
SearchDialogOverlay,
|
|
11
|
+
type SharedProps,
|
|
12
|
+
} from 'fumadocs-ui/components/dialog/search';
|
|
13
|
+
import { useDocsSearch } from 'fumadocs-core/search/client';
|
|
14
|
+
import { create } from '@orama/orama';
|
|
15
|
+
import { useI18n } from 'fumadocs-ui/contexts/i18n';
|
|
16
|
+
|
|
17
|
+
function initOrama() {
|
|
18
|
+
return create({
|
|
19
|
+
schema: { _: 'string' },
|
|
20
|
+
// https://docs.orama.com/docs/orama-js/supported-languages
|
|
21
|
+
language: 'english',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default function DefaultSearchDialog(props: SharedProps) {
|
|
26
|
+
const { locale } = useI18n(); // (optional) for i18n
|
|
27
|
+
const { search, setSearch, query } = useDocsSearch({
|
|
28
|
+
type: 'static',
|
|
29
|
+
initOrama,
|
|
30
|
+
locale,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<SearchDialog search={search} onSearchChange={setSearch} isLoading={query.isLoading} {...props}>
|
|
35
|
+
<SearchDialogOverlay />
|
|
36
|
+
<SearchDialogContent>
|
|
37
|
+
<SearchDialogHeader>
|
|
38
|
+
<SearchDialogIcon />
|
|
39
|
+
<SearchDialogInput />
|
|
40
|
+
<SearchDialogClose />
|
|
41
|
+
</SearchDialogHeader>
|
|
42
|
+
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
|
|
43
|
+
</SearchDialogContent>
|
|
44
|
+
</SearchDialog>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Hello World
|
|
3
|
+
description: Your first document
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Welcome to the docs! You can start writing documents in `/content/docs`.
|
|
7
|
+
|
|
8
|
+
## What is Next?
|
|
9
|
+
|
|
10
|
+
<Cards>
|
|
11
|
+
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
|
|
12
|
+
<Card title="Learn more about Fumadocs" href="https://fumadocs.dev" />
|
|
13
|
+
</Cards>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Components
|
|
3
|
+
description: Components
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Code Block
|
|
7
|
+
|
|
8
|
+
```js
|
|
9
|
+
console.log('Hello World');
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Cards
|
|
13
|
+
|
|
14
|
+
<Cards>
|
|
15
|
+
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
|
|
16
|
+
<Card title="Learn more about Fumadocs" href="https://fumadocs.dev" />
|
|
17
|
+
</Cards>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# deps
|
|
2
|
+
/node_modules
|
|
3
|
+
|
|
4
|
+
# generated content
|
|
5
|
+
.source
|
|
6
|
+
|
|
7
|
+
# test & build
|
|
8
|
+
/coverage
|
|
9
|
+
/.next/
|
|
10
|
+
/out/
|
|
11
|
+
/build
|
|
12
|
+
*.tsbuildinfo
|
|
13
|
+
|
|
14
|
+
# misc
|
|
15
|
+
.DS_Store
|
|
16
|
+
*.pem
|
|
17
|
+
/.pnp
|
|
18
|
+
.pnp.js
|
|
19
|
+
npm-debug.log*
|
|
20
|
+
yarn-debug.log*
|
|
21
|
+
yarn-error.log*
|
|
22
|
+
|
|
23
|
+
# others
|
|
24
|
+
.env*.local
|
|
25
|
+
.vercel
|
|
26
|
+
next-env.d.ts
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { docs } from 'fumadocs-mdx:collections/server';
|
|
2
|
+
import { type InferPageType, loader } from 'fumadocs-core/source';
|
|
3
|
+
|
|
4
|
+
// See https://fumadocs.dev/docs/headless/source-api for more info
|
|
5
|
+
export const source = loader({
|
|
6
|
+
baseUrl: '/docs',
|
|
7
|
+
source: docs.toFumadocsSource(),
|
|
8
|
+
plugins: [],
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export function getPageImage(page: InferPageType<typeof source>) {
|
|
12
|
+
const segments = [...page.slugs, 'image.png'];
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
segments,
|
|
16
|
+
url: `/og/docs/${segments.join('/')}`,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function getLLMText(page: InferPageType<typeof source>) {
|
|
21
|
+
const processed = await page.data.getText('processed');
|
|
22
|
+
|
|
23
|
+
return `# ${page.data.title}
|
|
24
|
+
|
|
25
|
+
${processed}`;
|
|
26
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "example-next-static",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "next build",
|
|
7
|
+
"dev": "next dev",
|
|
8
|
+
"start": "serve out",
|
|
9
|
+
"types:check": "fumadocs-mdx && next typegen && tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@orama/orama": "^3.1.18",
|
|
13
|
+
"fumadocs-core": "workspace:*",
|
|
14
|
+
"fumadocs-mdx": "workspace:*",
|
|
15
|
+
"fumadocs-ui": "workspace:*",
|
|
16
|
+
"lucide-react": "^0.562.0",
|
|
17
|
+
"next": "16.1.1",
|
|
18
|
+
"react": "^19.2.3",
|
|
19
|
+
"react-dom": "^19.2.3"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
23
|
+
"@types/mdx": "^2.0.13",
|
|
24
|
+
"@types/node": "^24.10.2",
|
|
25
|
+
"@types/react": "^19.2.7",
|
|
26
|
+
"@types/react-dom": "^19.2.3",
|
|
27
|
+
"postcss": "^8.5.6",
|
|
28
|
+
"serve": "^14.2.5",
|
|
29
|
+
"tailwindcss": "^4.1.18",
|
|
30
|
+
"typescript": "^5.9.3"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineConfig, defineDocs, frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';
|
|
2
|
+
|
|
3
|
+
// You can customise Zod schemas for frontmatter and `meta.json` here
|
|
4
|
+
// see https://fumadocs.dev/docs/mdx/collections
|
|
5
|
+
export const docs = defineDocs({
|
|
6
|
+
dir: 'content/docs',
|
|
7
|
+
docs: {
|
|
8
|
+
schema: frontmatterSchema,
|
|
9
|
+
postprocess: {
|
|
10
|
+
includeProcessedMarkdown: true,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
meta: {
|
|
14
|
+
schema: metaSchema,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export default defineConfig({
|
|
19
|
+
mdxOptions: {
|
|
20
|
+
// MDX options
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": ".",
|
|
4
|
+
"target": "ESNext",
|
|
5
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"forceConsistentCasingInFileNames": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"module": "esnext",
|
|
13
|
+
"moduleResolution": "bundler",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
"incremental": true,
|
|
18
|
+
"paths": {
|
|
19
|
+
"@/*": ["./*"],
|
|
20
|
+
"fumadocs-mdx:collections/*": [".source/*"]
|
|
21
|
+
},
|
|
22
|
+
"plugins": [
|
|
23
|
+
{
|
|
24
|
+
"name": "next"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"include": [
|
|
29
|
+
"next-env.d.ts",
|
|
30
|
+
"**/*.ts",
|
|
31
|
+
"**/*.tsx",
|
|
32
|
+
".next/types/**/*.ts",
|
|
33
|
+
".next/dev/types/**/*.ts"
|
|
34
|
+
],
|
|
35
|
+
"exclude": ["node_modules"]
|
|
36
|
+
}
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"types:check": "fumadocs-mdx && tsc --noEmit"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@tanstack/react-router": "1.
|
|
14
|
-
"@tanstack/react-router-devtools": "1.
|
|
15
|
-
"@tanstack/react-start": "1.
|
|
13
|
+
"@tanstack/react-router": "1.144.0",
|
|
14
|
+
"@tanstack/react-router-devtools": "1.144.0",
|
|
15
|
+
"@tanstack/react-start": "1.145.3",
|
|
16
16
|
"fumadocs-core": "workspace:*",
|
|
17
17
|
"fumadocs-mdx": "workspace:*",
|
|
18
18
|
"fumadocs-ui": "workspace:*",
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"@types/react": "^19.2.7",
|
|
30
30
|
"@types/react-dom": "^19.2.3",
|
|
31
31
|
"@vitejs/plugin-react": "^5.1.2",
|
|
32
|
-
"nitro": "3.0.1-alpha.1",
|
|
33
32
|
"tailwindcss": "^4.1.18",
|
|
34
33
|
"typescript": "^5.9.3",
|
|
35
34
|
"vite-tsconfig-paths": "^6.0.3"
|
|
@@ -4,7 +4,6 @@ import { defineConfig } from 'vite';
|
|
|
4
4
|
import tsConfigPaths from 'vite-tsconfig-paths';
|
|
5
5
|
import tailwindcss from '@tailwindcss/vite';
|
|
6
6
|
import mdx from 'fumadocs-mdx/vite';
|
|
7
|
-
import { nitro } from 'nitro/vite';
|
|
8
7
|
|
|
9
8
|
export default defineConfig({
|
|
10
9
|
server: {
|
|
@@ -22,8 +21,5 @@ export default defineConfig({
|
|
|
22
21
|
},
|
|
23
22
|
}),
|
|
24
23
|
react(),
|
|
25
|
-
// see https://tanstack.com/start/latest/docs/framework/react/guide/hosting for hosting config
|
|
26
|
-
// we configured nitro by default
|
|
27
|
-
nitro(),
|
|
28
24
|
],
|
|
29
25
|
});
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@orama/orama": "^3.1.18",
|
|
14
|
-
"@tanstack/react-router": "1.
|
|
15
|
-
"@tanstack/react-router-devtools": "1.
|
|
16
|
-
"@tanstack/react-start": "1.
|
|
17
|
-
"@tanstack/start-static-server-functions": "1.
|
|
14
|
+
"@tanstack/react-router": "1.144.0",
|
|
15
|
+
"@tanstack/react-router-devtools": "1.144.0",
|
|
16
|
+
"@tanstack/react-start": "1.145.3",
|
|
17
|
+
"@tanstack/start-static-server-functions": "1.145.3",
|
|
18
18
|
"fumadocs-core": "workspace:*",
|
|
19
19
|
"fumadocs-mdx": "workspace:*",
|
|
20
20
|
"fumadocs-ui": "workspace:*",
|
|
@@ -10,13 +10,15 @@
|
|
|
10
10
|
"types:check": "fumadocs-mdx && tsc --noEmit"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
+
"@fumadocs/ui": "workspace:*",
|
|
13
14
|
"fumadocs-core": "workspace:*",
|
|
14
15
|
"fumadocs-mdx": "workspace:*",
|
|
15
16
|
"fumadocs-ui": "workspace:*",
|
|
17
|
+
"lucide-react": "^0.562.0",
|
|
16
18
|
"react": "^19.2.3",
|
|
17
19
|
"react-dom": "^19.2.3",
|
|
18
20
|
"react-server-dom-webpack": "^19.2.3",
|
|
19
|
-
"waku": "
|
|
21
|
+
"waku": "1.0.0-alpha.0"
|
|
20
22
|
},
|
|
21
23
|
"devDependencies": {
|
|
22
24
|
"@tailwindcss/vite": "^4.1.18",
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { loader } from 'fumadocs-core/source';
|
|
2
|
+
import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
|
|
2
3
|
import { docs } from 'fumadocs-mdx:collections/server';
|
|
3
4
|
|
|
4
5
|
export const source = loader({
|
|
5
6
|
source: docs.toFumadocsSource(),
|
|
6
7
|
baseUrl: '/docs',
|
|
8
|
+
plugins: [lucideIconsPlugin()],
|
|
7
9
|
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants-CReWPhck.js","names":["result: Partial<T>","templates: TemplateInfo[]","versionPkg.dependencies","coreVersion","uiVersion","mdxVersion"],"sources":["../src/utils.ts","../../create-app-versions/package.json","../../core/package.json","../../ui/package.json","../../mdx/package.json","../src/constants.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path, { join } from 'node:path';\nimport { x } from 'tinyexec';\n\nexport async function writeFile(file: string, content: string) {\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(file, content);\n}\n\nexport async function copy(\n from: string,\n to: string,\n options: {\n rename?: (s: string) => string;\n filter?: (s: string) => boolean;\n filterDir?: (dir: string) => boolean;\n } = {},\n): Promise<void> {\n const { rename = (s) => s, filterDir = () => true, filter = () => true } = options;\n const stats = await fs.stat(from);\n\n if (stats.isDirectory() && filterDir(from)) {\n const files = await fs.readdir(from);\n\n await Promise.all(\n files.map((file) => copy(path.join(from, file), path.join(to, file), options)),\n );\n }\n\n if (stats.isFile() && filter(from)) {\n to = rename(to);\n await fs.mkdir(path.dirname(to), { recursive: true });\n await fs.copyFile(from, to);\n }\n}\n\nasync function isInGitRepository(cwd: string) {\n const { exitCode } = await x('git', ['rev-parse', '--is-inside-work-tree'], {\n nodeOptions: { cwd },\n });\n\n return exitCode === 0;\n}\n\nasync function isDefaultBranchSet(cwd: string) {\n const { exitCode } = await x('git', ['config', 'init.defaultBranch'], {\n nodeOptions: { cwd },\n });\n\n return exitCode === 0;\n}\n\n/*\nInitialize a Git repo on the project.\n\nBased on https://github.com/vercel/next.js/blob/canary/packages/create-next-app/helpers/git.ts\n*/\nexport async function tryGitInit(cwd: string): Promise<boolean> {\n const { exitCode } = await x('git', ['--version']);\n if (exitCode !== 0) return false;\n\n if (await isInGitRepository(cwd)) return false;\n\n try {\n await x('git', ['init'], {\n throwOnError: true,\n nodeOptions: { cwd },\n });\n\n if (!(await isDefaultBranchSet(cwd))) {\n await x('git', ['checkout', '-b', 'main'], {\n throwOnError: true,\n nodeOptions: {\n cwd,\n },\n });\n }\n\n await x('git', ['add', '-A'], {\n throwOnError: true,\n nodeOptions: {\n cwd,\n },\n });\n\n await x('git', ['commit', '-m', 'Initial commit from Create Fumadocs App'], {\n throwOnError: true,\n nodeOptions: {\n cwd,\n },\n });\n return true;\n } catch {\n await fs.rmdir(join(cwd, '.git'), { recursive: true }).catch(() => null);\n\n return false;\n }\n}\n\nexport function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\n const result: Partial<T> = {};\n\n for (const key of keys) {\n if (key in obj) {\n result[key] = obj[key];\n }\n }\n\n return result as Pick<T, K>;\n}\n","","","","","import { fileURLToPath } from 'node:url';\nimport versionPkg from '../../create-app-versions/package.json';\nimport { version as coreVersion } from '../../core/package.json';\nimport { version as uiVersion } from '../../ui/package.json';\nimport { version as mdxVersion } from '../../mdx/package.json';\n\nexport const sourceDir = fileURLToPath(new URL(`../`, import.meta.url).href);\n\nexport const isCI = Boolean(process.env.CI);\n\nexport interface TemplateInfo {\n value:\n | '+next+fuma-docs-mdx'\n | 'waku'\n | 'react-router'\n | 'react-router-spa'\n | 'tanstack-start'\n | 'tanstack-start-spa';\n label: string;\n appDir: string;\n /**\n * path to root provider, relative to `appDir``\n */\n rootProviderPath: string;\n hint?: string;\n /**\n * rename files when copying from template\n */\n rename?: (name: string) => string;\n}\n\nexport const templates: TemplateInfo[] = [\n {\n value: '+next+fuma-docs-mdx',\n label: 'Next.js: Fumadocs MDX',\n hint: 'recommended',\n appDir: '',\n rootProviderPath: 'app/layout.tsx',\n },\n {\n value: 'waku',\n label: 'Waku: Fumadocs MDX',\n appDir: 'src',\n rootProviderPath: 'components/provider.tsx',\n },\n {\n value: 'react-router',\n label: 'React Router: Fumadocs MDX (not RSC)',\n appDir: 'app',\n rootProviderPath: 'root.tsx',\n },\n {\n value: 'react-router-spa',\n label: 'React Router SPA: Fumadocs MDX (not RSC)',\n hint: 'SPA mode allows you to host the site statically, compatible with a CDN.',\n appDir: 'app',\n rootProviderPath: 'root.tsx',\n },\n {\n value: 'tanstack-start',\n label: 'Tanstack Start: Fumadocs MDX (not RSC)',\n appDir: 'src',\n rootProviderPath: 'routes/__root.tsx',\n },\n {\n value: 'tanstack-start-spa',\n label: 'Tanstack Start SPA: Fumadocs MDX (not RSC)',\n hint: 'SPA mode allows you to host the site statically, compatible with a CDN.',\n appDir: 'src',\n rootProviderPath: 'routes/__root.tsx',\n },\n];\n\nexport const depVersions = {\n ...versionPkg.dependencies,\n 'fumadocs-core': coreVersion,\n 'fumadocs-ui': uiVersion,\n 'fumadocs-mdx': mdxVersion,\n};\n"],"mappings":"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"}
|