CLI: Support Biome for other templates

This commit is contained in:
Fuma Nama
2025-10-26 19:13:44 +08:00
parent f0bbda7001
commit e051a7f3ff
9 changed files with 116 additions and 49 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'create-fumadocs-app': patch
---
Support Biome for other templates
+28 -16
View File
@@ -26,7 +26,7 @@ const command = program
.addOption(
new Option(
'--linter <name>',
'(Next.js only) configure a linter/formatter',
'configure a linter/formatter, ESLint is currently Next.js only.',
).choices(['eslint', 'biome']),
)
.addOption(
@@ -85,24 +85,36 @@ async function main(): Promise<void> {
},
lint: async ({ results }: { results: { template?: Template } }) => {
if (config.linter !== undefined) return config.linter;
if (isCI || !results.template?.startsWith('+next')) return 'disabled';
if (isCI) return 'disabled';
return select({
message: 'Configure linter?',
options: [
{
value: 'disabled',
label: 'Disabled',
},
{
value: 'eslint',
label: 'ESLint',
},
{
value: 'biome',
label: 'Biome',
},
],
options:
results.template === '+next+fuma-docs-mdx'
? [
{
value: 'disabled',
label: 'Disabled',
},
{
value: 'eslint',
label: 'ESLint',
},
{
value: 'biome',
label: 'Biome',
},
]
: [
{
value: 'disabled',
label: 'Disabled',
},
{
value: 'biome',
label: 'Biome',
},
],
});
},
search: async () => {
@@ -0,0 +1,33 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": ["**", "!node_modules", "!.source"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
},
"domains": {
"react": "recommended"
}
},
"assist": {
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
+11 -3
View File
@@ -1,7 +1,9 @@
import { TemplatePlugin } from '@/index';
import { copy, pick } from '@/utils';
import { pick, writeFile } from '@/utils';
import path from 'node:path';
import { depVersions, sourceDir } from '@/constants';
import { depVersions } from '@/constants';
import base from './biome.base.json';
import next from './biome.next.json';
export function biome(): TemplatePlugin {
return {
@@ -20,7 +22,13 @@ export function biome(): TemplatePlugin {
};
},
async afterWrite() {
await copy(path.join(sourceDir, `template/+next+biome`), this.dest);
const config =
this.template.value === '+next+fuma-docs-mdx' ? next : base;
await writeFile(
path.join(this.dest, 'biome.json'),
JSON.stringify(config, null, 2),
);
this.log('Configured Biome');
},
};
+34 -3
View File
@@ -1,11 +1,40 @@
import { TemplatePlugin } from '@/index';
import { copy } from '@/utils';
import { writeFile } from '@/utils';
import path from 'node:path';
import { depVersions, sourceDir } from '@/constants';
import { depVersions } from '@/constants';
const config = `import { dirname } from 'path';
import { fileURLToPath } from 'url';
import { FlatCompat } from '@eslint/eslintrc';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends('next/core-web-vitals', 'next/typescript'),
{
ignores: [
'node_modules/**',
'.next/**',
'out/**',
'build/**',
'.source/**',
'next-env.d.ts',
],
},
];
export default eslintConfig;`;
export function eslint(): TemplatePlugin {
return {
packageJson(packageJson) {
if (this.template.value !== '+next+fuma-docs-mdx') return;
return {
...packageJson,
scripts: {
@@ -21,7 +50,9 @@ export function eslint(): TemplatePlugin {
};
},
async afterWrite() {
await copy(path.join(sourceDir, `template/+next+eslint`), this.dest);
if (this.template.value !== '+next+fuma-docs-mdx') return;
await writeFile(path.join(this.dest, 'eslint.config.mjs'), config);
this.log('Configured ESLint');
},
};
@@ -8,6 +8,8 @@ import fs from 'node:fs/promises';
export function nextUseSrc(): TemplatePlugin {
return {
template(info) {
if (info.value !== '+next+fuma-docs-mdx') return;
return {
...info,
appDir: 'src',
@@ -26,6 +28,8 @@ export function nextUseSrc(): TemplatePlugin {
},
// update tsconfig.json for src dir
async afterWrite() {
if (this.template.value !== '+next+fuma-docs-mdx') return;
const tsconfigPath = path.join(this.dest, 'tsconfig.json');
const content = (await fs.readFile(tsconfigPath)).toString();
const config = JSON.parse(content);
@@ -72,7 +72,7 @@ See https://fumadocs.dev/docs/headless/search/orama-cloud for integrating Orama
} else {
await Promise.all([
fs.unlink(path.join(appDir, 'pages/api/search.ts')).catch(() => null),
writeFile(path.join(appDir, 'pages/api/static.json.ts'), route.waku),
writeFile(path.join(appDir, 'pages/static.json.ts'), route.waku),
]);
}
@@ -1,26 +0,0 @@
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import { FlatCompat } from '@eslint/eslintrc';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends('next/core-web-vitals', 'next/typescript'),
{
ignores: [
'node_modules/**',
'.next/**',
'out/**',
'build/**',
'.source/**',
'next-env.d.ts',
],
},
];
export default eslintConfig;