pull/336/head
xingyu4j 2026-03-14 11:34:06 +08:00
commit ac3fc6b7d3
389 changed files with 8904 additions and 8239 deletions

7
.gitignore vendored
View File

@ -50,3 +50,10 @@ vite.config.ts.*
*.sw? *.sw?
.history .history
.cursor .cursor
# AI
.agent
.agents
.claude
.codex
skills-lock.json

4
.npmrc
View File

@ -1,8 +1,8 @@
registry=https://registry.npmmirror.com registry=https://registry.npmmirror.com
public-hoist-pattern[]=lefthook public-hoist-pattern[]=lefthook
public-hoist-pattern[]=eslint public-hoist-pattern[]=eslint
public-hoist-pattern[]=prettier public-hoist-pattern[]=oxfmt
public-hoist-pattern[]=prettier-plugin-tailwindcss public-hoist-pattern[]=oxlint
public-hoist-pattern[]=stylelint public-hoist-pattern[]=stylelint
public-hoist-pattern[]=*postcss* public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=@commitlint/* public-hoist-pattern[]=@commitlint/*

View File

@ -1,18 +0,0 @@
dist
dev-dist
.local
.output.js
node_modules
.nvmrc
coverage
CODEOWNERS
.nitro
.output
**/*.svg
**/*.sh
public
.npmrc
*-lock.yaml

View File

@ -1 +0,0 @@
export { default } from '@vben/prettier-config';

View File

@ -2,3 +2,7 @@ dist
public public
__tests__ __tests__
coverage coverage
.codex
.claude
.agent
.agents

View File

@ -2,12 +2,12 @@
"recommendations": [ "recommendations": [
// Vue 3 // Vue 3
"Vue.volar", "Vue.volar",
// ESLint JavaScript VS Code // oxlint VS Code
"dbaeumer.vscode-eslint", "oxc.oxc-vscode",
// Visual Studio Code Stylelint // Visual Studio Code Stylelint
"stylelint.vscode-stylelint", "stylelint.vscode-stylelint",
// 使 Prettier // 使 oxfmt
"esbenp.prettier-vscode", "oxc.oxc-vscode",
// dotenv // dotenv
"mikestead.dotenv", "mikestead.dotenv",
// //

46
.vscode/settings.json vendored
View File

@ -1,5 +1,6 @@
{ {
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts", "tailwindCSS.experimental.configFile": "packages/@core/base/design/src/css/global.css",
"tailwindCSS.lint.suggestCanonicalClasses": "ignore",
// workbench // workbench
"workbench.list.smoothScrolling": true, "workbench.list.smoothScrolling": true,
"workbench.startupEditor": "newUntitledFile", "workbench.startupEditor": "newUntitledFile",
@ -31,39 +32,49 @@
"editor.autoClosingOvertype": "always", "editor.autoClosingOvertype": "always",
"editor.autoClosingQuotes": "beforeWhitespace", "editor.autoClosingQuotes": "beforeWhitespace",
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?", "editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
"editor.quickSuggestions": {
"strings": "on"
},
// lint && format
"oxc.enable": true,
"oxc.typeAware": true,
"oxc.configPath": "oxlint.config.ts",
"oxc.fmt.configPath": "oxfmt.config.ts",
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit", "source.fixAll.oxc": "explicit",
"source.fixAll.stylelint": "explicit", "source.fixAll.stylelint": "explicit",
"source.organizeImports": "never" "source.organizeImports": "never"
}, },
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "oxc.oxc-vscode",
"[html]": { "[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[css]": { "[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[scss]": { "[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[javascript]": { "[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[json]": { "[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[markdown]": { "[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[jsonc]": { "[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
"[vue]": { "[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "oxc.oxc-vscode"
}, },
// extensions // extensions
"extensions.ignoreRecommendations": true, "extensions.ignoreRecommendations": true,
@ -79,6 +90,7 @@
"files.insertFinalNewline": true, "files.insertFinalNewline": true,
"files.simpleDialog.enable": true, "files.simpleDialog.enable": true,
"files.associations": { "files.associations": {
"*.css": "tailwindcss",
"*.ejs": "html", "*.ejs": "html",
"*.art": "html", "*.art": "html",
"**/tsconfig.json": "jsonc", "**/tsconfig.json": "jsonc",
@ -118,7 +130,7 @@
// search // search
"search.searchEditor.singleClickBehaviour": "peekDefinition", "search.searchEditor.singleClickBehaviour": "peekDefinition",
"search.followSymlinks": false, "search.followSymlinks": false,
// 使/ // 使
"search.exclude": { "search.exclude": {
"**/node_modules": true, "**/node_modules": true,
"**/*.log": true, "**/*.log": true,
@ -193,7 +205,7 @@
"*": false "*": false
}, },
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"], "cssVariables.lookupFiles": ["packages/@core/base/design/src/**/*.css"],
"i18n-ally.localesPaths": [ "i18n-ally.localesPaths": [
"packages/locales/src/langs", "packages/locales/src/langs",
@ -218,12 +230,10 @@
"*.env": "$(capture).env.*", "*.env": "$(capture).env.*",
"README.md": "README*,CHANGELOG*,LICENSE,CNAME", "README.md": "README*,CHANGELOG*,LICENSE,CNAME",
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json", "package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml", "oxlint.config.ts": ".eslintignore,.stylelintignore,.commitlintrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml,oxfmt.config.*,eslint.config.*"
"tailwind.config.mjs": "postcss.*"
}, },
"commentTranslate.hover.enabled": false, "commentTranslate.hover.enabled": false,
"commentTranslate.multiLineMerge": true, "commentTranslate.multiLineMerge": true,
"vue.server.hybridMode": true, "vue.server.hybridMode": true,
"typescript.tsdk": "node_modules/typescript/lib", "typescript.tsdk": "node_modules/typescript/lib"
"oxc.enable": false
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/web-antd", "name": "@vben/web-antd",
"version": "5.6.0", "version": "5.7.0",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config/postcss';

View File

@ -76,10 +76,10 @@ const chartTabs: TabOption[] = [
</AnalysisChartsTabs> </AnalysisChartsTabs>
<div class="mt-5 w-full md:flex"> <div class="mt-5 w-full md:flex">
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问数量"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问数量">
<AnalyticsVisitsData /> <AnalyticsVisitsData />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问来源">
<AnalyticsVisitsSource /> <AnalyticsVisitsSource />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config';

View File

@ -2,7 +2,6 @@
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web-app.json", "extends": "@vben/tsconfig/web-app.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"#/*": ["./src/*"] "#/*": ["./src/*"]
}, },

View File

@ -6,5 +6,5 @@
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"noEmit": false "noEmit": false
}, },
"include": ["vite.config.mts"] "include": ["vite.config.ts"]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/web-antdv-next", "name": "@vben/web-antdv-next",
"version": "5.6.0", "version": "5.7.0",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config/postcss';

View File

@ -98,8 +98,7 @@ export const useAuthStore = defineStore('auth', () => {
} }
async function fetchUserInfo() { async function fetchUserInfo() {
let userInfo: null | UserInfo = null; const userInfo = await getUserInfoApi();
userInfo = await getUserInfoApi();
userStore.setUserInfo(userInfo); userStore.setUserInfo(userInfo);
return userInfo; return userInfo;
} }

View File

@ -55,8 +55,7 @@ const formSchema = computed((): VbenFormSchema[] => {
* @param values 登录表单数据 * @param values 登录表单数据
*/ */
async function handleLogin(values: Recordable<any>) { async function handleLogin(values: Recordable<any>) {
// eslint-disable-next-line no-console void values;
console.log(values);
} }
</script> </script>

View File

@ -29,8 +29,7 @@ const formSchema = computed((): VbenFormSchema[] => {
}); });
function handleSubmit(value: Recordable<any>) { function handleSubmit(value: Recordable<any>) {
// eslint-disable-next-line no-console void value;
console.log('reset email:', value);
} }
</script> </script>

View File

@ -82,8 +82,7 @@ const formSchema = computed((): VbenFormSchema[] => {
}); });
function handleSubmit(value: Recordable<any>) { function handleSubmit(value: Recordable<any>) {
// eslint-disable-next-line no-console void value;
console.log('register submit:', value);
} }
</script> </script>

View File

@ -76,10 +76,10 @@ const chartTabs: TabOption[] = [
</AnalysisChartsTabs> </AnalysisChartsTabs>
<div class="mt-5 w-full md:flex"> <div class="mt-5 w-full md:flex">
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问数量"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问数量">
<AnalyticsVisitsData /> <AnalyticsVisitsData />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问来源">
<AnalyticsVisitsSource /> <AnalyticsVisitsSource />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config';

View File

@ -2,7 +2,6 @@
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web-app.json", "extends": "@vben/tsconfig/web-app.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"#/*": ["./src/*"] "#/*": ["./src/*"]
} }

View File

@ -6,5 +6,5 @@
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"noEmit": false "noEmit": false
}, },
"include": ["vite.config.mts"] "include": ["vite.config.ts"]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/web-ele", "name": "@vben/web-ele",
"version": "5.6.0", "version": "5.7.0",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config/postcss';

View File

@ -0,0 +1,4 @@
declare module 'element-plus/es/components/*/style/css' {
const sideEffect: undefined;
export default sideEffect;
}

View File

@ -76,10 +76,10 @@ const chartTabs: TabOption[] = [
</AnalysisChartsTabs> </AnalysisChartsTabs>
<div class="mt-5 w-full md:flex"> <div class="mt-5 w-full md:flex">
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问数量"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问数量">
<AnalyticsVisitsData /> <AnalyticsVisitsData />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问来源">
<AnalyticsVisitsSource /> <AnalyticsVisitsSource />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config';

View File

@ -2,7 +2,6 @@
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web-app.json", "extends": "@vben/tsconfig/web-app.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"#/*": ["./src/*"] "#/*": ["./src/*"]
}, },

View File

@ -6,5 +6,5 @@
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"noEmit": false "noEmit": false
}, },
"include": ["vite.config.mts"] "include": ["vite.config.ts"]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/web-naive", "name": "@vben/web-naive",
"version": "5.6.0", "version": "5.7.0",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config/postcss';

View File

@ -76,10 +76,10 @@ const chartTabs: TabOption[] = [
</AnalysisChartsTabs> </AnalysisChartsTabs>
<div class="mt-5 w-full md:flex"> <div class="mt-5 w-full md:flex">
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问数量"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问数量">
<AnalyticsVisitsData /> <AnalyticsVisitsData />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问来源">
<AnalyticsVisitsSource /> <AnalyticsVisitsSource />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config';

View File

@ -2,7 +2,6 @@
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web-app.json", "extends": "@vben/tsconfig/web-app.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"#/*": ["./src/*"] "#/*": ["./src/*"]
} }

View File

@ -6,5 +6,5 @@
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"noEmit": false "noEmit": false
}, },
"include": ["vite.config.mts"] "include": ["vite.config.ts"]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/web-tdesign", "name": "@vben/web-tdesign",
"version": "5.6.0", "version": "5.7.0",
"homepage": "https://vben.pro", "homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config/postcss';

View File

@ -76,10 +76,10 @@ const chartTabs: TabOption[] = [
</AnalysisChartsTabs> </AnalysisChartsTabs>
<div class="mt-5 w-full md:flex"> <div class="mt-5 w-full md:flex">
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问数量"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问数量">
<AnalyticsVisitsData /> <AnalyticsVisitsData />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:mr-4 md:w-1/3" title="访问来源">
<AnalyticsVisitsSource /> <AnalyticsVisitsSource />
</AnalysisChartCard> </AnalysisChartCard>
<AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源"> <AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">

View File

@ -1 +0,0 @@
export { default } from '@vben/tailwind-config';

View File

@ -2,7 +2,6 @@
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web-app.json", "extends": "@vben/tsconfig/web-app.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"#/*": ["./src/*"] "#/*": ["./src/*"]
} }

View File

@ -6,5 +6,5 @@
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"noEmit": false "noEmit": false
}, },
"include": ["vite.config.mts"] "include": ["vite.config.ts"]
} }

View File

@ -15,6 +15,7 @@
"cascader", "cascader",
"clsx", "clsx",
"cropperjs", "cropperjs",
"dedup",
"defu", "defu",
"demi", "demi",
"dotenv", "dotenv",
@ -46,6 +47,9 @@
"noreferrer", "noreferrer",
"nprogress", "nprogress",
"nuxt", "nuxt",
"organisation",
"oxfmt",
"oxlint",
"pinia", "pinia",
"prefixs", "prefixs",
"publint", "publint",
@ -56,8 +60,11 @@
"sonner", "sonner",
"sortablejs", "sortablejs",
"styl", "styl",
"tabler",
"taze", "taze",
"tdesign", "tdesign",
"tsgolint",
"Turborepo",
"ui-kit", "ui-kit",
"uicons", "uicons",
"unplugin", "unplugin",

View File

@ -27,7 +27,7 @@ const parsedFiles = computed(() => {
<ClientOnly> <ClientOnly>
<slot v-if="parsedFiles.length > 0"></slot> <slot v-if="parsedFiles.length > 0"></slot>
<div v-else class="text-sm text-destructive"> <div v-else class="text-sm text-destructive">
<span class="rounded-sm bg-destructive px-1 py-1 text-foreground"> <span class="rounded-sm bg-destructive p-1 text-foreground">
ERROR: ERROR:
</span> </span>
The preview directory does not exist. Please check the 'dir' The preview directory does not exist. Please check the 'dir'

View File

@ -56,15 +56,15 @@ const toggleOpen = () => {
<TabsList class="relative flex"> <TabsList class="relative flex">
<template v-if="open"> <template v-if="open">
<TabsIndicator <TabsIndicator
class="absolute bottom-0 left-0 h-[2px] w-[--reka-tabs-indicator-size] translate-x-[--reka-tabs-indicator-position] rounded-full transition-[width,transform] duration-300" class="absolute bottom-0 left-0 h-[2px] w-(--reka-tabs-indicator-size) translate-x-(--reka-tabs-indicator-position) rounded-full transition-[width,transform] duration-300"
> >
<div class="size-full bg-[var(--vp-c-indigo-1)]"></div> <div class="size-full bg-(--vp-c-indigo-1)"></div>
</TabsIndicator> </TabsIndicator>
<TabsTrigger <TabsTrigger
v-for="(tab, index) in tabs" v-for="(tab, index) in tabs"
:key="index" :key="index"
:value="tab.label" :value="tab.label"
class="border-box px-4 py-3 text-foreground data-[state=active]:text-[var(--vp-c-indigo-1)]" class="border-box px-4 py-3 text-foreground data-[state=active]:text-(--vp-c-indigo-1)"
tabindex="-1" tabindex="-1"
> >
{{ tab.label }} {{ tab.label }}
@ -92,7 +92,7 @@ const toggleOpen = () => {
</div> </div>
<div <div
:class="`${open ? 'h-[unset] max-h-[80vh]' : 'h-0'}`" :class="`${open ? 'h-[unset] max-h-[80vh]' : 'h-0'}`"
class="block overflow-y-scroll bg-[var(--vp-code-block-bg)] transition-all duration-300" class="block overflow-y-scroll bg-(--vp-code-block-bg) transition-all duration-300"
> >
<TabsContent <TabsContent
v-for="tab in tabs" v-for="tab in tabs"

View File

@ -5,7 +5,6 @@ import { readdirSync } from 'node:fs';
import { join } from 'node:path'; import { join } from 'node:path';
export const rawPathRegexp = export const rawPathRegexp =
// eslint-disable-next-line regexp/no-super-linear-backtracking, regexp/strict
/^(.+?(?:\.([\da-z]+))?)(#[\w-]+)?(?: ?{(\d+(?:[,-]\d+)*)? ?(\S+)?})? ?(?:\[(.+)])?$/; /^(.+?(?:\.([\da-z]+))?)(#[\w-]+)?(?: ?{(\d+(?:[,-]\d+)*)? ?(\S+)?})? ?(?:\[(.+)])?$/;
function rawPathToToken(rawPath: string) { function rawPathToToken(rawPath: string) {

View File

@ -12,7 +12,7 @@ import {
GitChangelog, GitChangelog,
GitChangelogMarkdownSection, GitChangelogMarkdownSection,
} from '@nolebase/vitepress-plugin-git-changelog/vite'; } from '@nolebase/vitepress-plugin-git-changelog/vite';
import tailwind from 'tailwindcss'; import tailwindcss from '@tailwindcss/vite';
import { defineConfig, postcssIsolateStyles } from 'vitepress'; import { defineConfig, postcssIsolateStyles } from 'vitepress';
import { import {
groupIconMdPlugin, groupIconMdPlugin,
@ -57,10 +57,7 @@ export const shared = defineConfig({
}, },
css: { css: {
postcss: { postcss: {
plugins: [ plugins: [postcssIsolateStyles({ includeFiles: [/vp-doc\.css/] })],
tailwind(),
postcssIsolateStyles({ includeFiles: [/vp-doc\.css/] }),
],
}, },
preprocessorOptions: { preprocessorOptions: {
scss: { scss: {
@ -72,6 +69,7 @@ export const shared = defineConfig({
stringify: true, stringify: true,
}, },
plugins: [ plugins: [
tailwindcss(),
GitChangelog({ GitChangelog({
mapAuthors: [ mapAuthors: [
{ {

View File

@ -1,7 +1,7 @@
<script setup lang="ts"></script> <script setup lang="ts"></script>
<template> <template>
<div class="vp-doc vben-contributors"> <div class="vben-contributors vp-doc">
<p>Contributors</p> <p>Contributors</p>
<a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors"> <a href="https://github.com/vbenjs/vue-vben-admin/graphs/contributors">
<img <img

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/docs", "name": "@vben/docs",
"version": "5.6.0", "version": "5.7.0",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "vitepress build", "build": "vitepress build",
@ -27,6 +27,7 @@
}, },
"devDependencies": { "devDependencies": {
"@nolebase/vitepress-plugin-git-changelog": "catalog:", "@nolebase/vitepress-plugin-git-changelog": "catalog:",
"@tailwindcss/vite": "catalog:",
"@vben/vite-config": "workspace:*", "@vben/vite-config": "workspace:*",
"@vite-pwa/vitepress": "catalog:", "@vite-pwa/vitepress": "catalog:",
"vitepress": "catalog:", "vitepress": "catalog:",

View File

@ -219,6 +219,7 @@ const defaultPreferences: Preferences = {
dynamicTitle: true, dynamicTitle: true,
enableCheckUpdates: true, enableCheckUpdates: true,
enablePreferences: true, enablePreferences: true,
enableCopyPreferences: true,
enableRefreshToken: false, enableRefreshToken: false,
isMobile: false, isMobile: false,
layout: 'sidebar-nav', layout: 'sidebar-nav',
@ -376,6 +377,8 @@ interface AppPreferences {
enableCheckUpdates: boolean; enableCheckUpdates: boolean;
/** Whether to display preferences */ /** Whether to display preferences */
enablePreferences: boolean; enablePreferences: boolean;
/** Whether to display copy preferences button */
enableCopyPreferences: boolean;
/** /**
* @zh_CN Whether to enable refreshToken * @zh_CN Whether to enable refreshToken
*/ */

View File

@ -599,6 +599,13 @@ _注意:_ 排序仅针对一级菜单有效,二级菜单的排序需要在对
用于配置当前路由不使用基础布局,仅在顶级时生效。默认情况下,所有的路由都会被包裹在基础布局中(包含顶部以及侧边等导航部件),如果你的页面不需要这些部件,可以设置 `noBasicLayout``true` 用于配置当前路由不使用基础布局,仅在顶级时生效。默认情况下,所有的路由都会被包裹在基础布局中(包含顶部以及侧边等导航部件),如果你的页面不需要这些部件,可以设置 `noBasicLayout``true`
### domCached
- 类型:`boolean`
- 默认值:`false`
用于配置当前路由是否要将route对应dom元素缓存起来。对于一些复杂页面切换tab浏览器回流/重绘会导致卡顿, `domCached` 设为 `true`可解决该问题但是也有代价1、内存占用升高 2、vue的部分生命周期不会触发
## 路由刷新 ## 路由刷新
路由刷新方式如下: 路由刷新方式如下:

View File

@ -218,6 +218,7 @@ const defaultPreferences: Preferences = {
dynamicTitle: true, dynamicTitle: true,
enableCheckUpdates: true, enableCheckUpdates: true,
enablePreferences: true, enablePreferences: true,
enableCopyPreferences: true,
enableRefreshToken: false, enableRefreshToken: false,
isMobile: false, isMobile: false,
layout: 'sidebar-nav', layout: 'sidebar-nav',
@ -375,6 +376,8 @@ interface AppPreferences {
enableCheckUpdates: boolean; enableCheckUpdates: boolean;
/** 是否显示偏好设置 */ /** 是否显示偏好设置 */
enablePreferences: boolean; enablePreferences: boolean;
/** 是否显示复制偏好设置按钮 */
enableCopyPreferences: boolean;
/** /**
* @zh_CN 是否开启refreshToken * @zh_CN 是否开启refreshToken
*/ */

View File

@ -1,11 +0,0 @@
import tailwindcssConfig from '@vben/tailwind-config';
export default {
...tailwindcssConfig,
content: [
...tailwindcssConfig.content,
'.vitepress/**/*.{js,mts,ts,vue}',
'src/demos/**/*.{js,mts,ts,vue}',
'src/**/*.md',
],
};

View File

@ -2,7 +2,6 @@
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web.json", "extends": "@vben/tsconfig/web.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".",
"paths": { "paths": {
"#/*": ["./src/_env/*"] "#/*": ["./src/_env/*"]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/commitlint-config", "name": "@vben/commitlint-config",
"version": "5.6.0", "version": "5.7.0",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",

View File

@ -1,6 +1,6 @@
{ {
"name": "@vben/eslint-config", "name": "@vben/eslint-config",
"version": "5.6.0", "version": "5.7.0",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
@ -27,32 +27,26 @@
} }
}, },
"dependencies": { "dependencies": {
"@vben/oxlint-config": "workspace:*",
"eslint-config-turbo": "catalog:", "eslint-config-turbo": "catalog:",
"eslint-plugin-command": "catalog:", "eslint-plugin-command": "catalog:"
"eslint-plugin-import-x": "catalog:"
}, },
"devDependencies": { "devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "catalog:",
"@eslint/js": "catalog:", "@eslint/js": "catalog:",
"@types/eslint": "catalog:",
"@typescript-eslint/eslint-plugin": "catalog:", "@typescript-eslint/eslint-plugin": "catalog:",
"@typescript-eslint/parser": "catalog:", "@typescript-eslint/parser": "catalog:",
"eslint": "catalog:", "eslint": "catalog:",
"eslint-plugin-eslint-comments": "catalog:",
"eslint-plugin-jsdoc": "catalog:",
"eslint-plugin-jsonc": "catalog:", "eslint-plugin-jsonc": "catalog:",
"eslint-plugin-n": "catalog:", "eslint-plugin-n": "catalog:",
"eslint-plugin-no-only-tests": "catalog:", "eslint-plugin-oxlint": "catalog:",
"eslint-plugin-perfectionist": "catalog:", "eslint-plugin-perfectionist": "catalog:",
"eslint-plugin-pnpm": "catalog:", "eslint-plugin-pnpm": "catalog:",
"eslint-plugin-prettier": "catalog:",
"eslint-plugin-regexp": "catalog:",
"eslint-plugin-unicorn": "catalog:", "eslint-plugin-unicorn": "catalog:",
"eslint-plugin-unused-imports": "catalog:", "eslint-plugin-unused-imports": "catalog:",
"eslint-plugin-vitest": "catalog:",
"eslint-plugin-vue": "catalog:", "eslint-plugin-vue": "catalog:",
"eslint-plugin-yml": "catalog:", "eslint-plugin-yml": "catalog:",
"globals": "catalog:", "globals": "catalog:",
"jsonc-eslint-parser": "catalog:",
"vue-eslint-parser": "catalog:", "vue-eslint-parser": "catalog:",
"yaml-eslint-parser": "catalog:" "yaml-eslint-parser": "catalog:"
} }

View File

@ -3,10 +3,9 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
export async function comments(): Promise<Linter.Config[]> { export async function comments(): Promise<Linter.Config[]> {
const [pluginComments] = await Promise.all([ const pluginComments = await interopDefault(
// @ts-expect-error - no types import('@eslint-community/eslint-plugin-eslint-comments'),
interopDefault(import('eslint-plugin-eslint-comments')), );
] as const);
return [ return [
{ {

View File

@ -1,28 +0,0 @@
import type { Linter } from 'eslint';
export async function disableds(): Promise<Linter.Config[]> {
return [
{
files: ['**/__tests__/**/*.?([cm])[jt]s?(x)'],
name: 'disables/test',
rules: {
'@typescript-eslint/ban-ts-comment': 'off',
'no-console': 'off',
},
},
{
files: ['**/*.d.ts'],
name: 'disables/dts',
rules: {
'@typescript-eslint/triple-slash-reference': 'off',
},
},
{
files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
name: 'disables/js',
rules: {
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
},
];
}

View File

@ -50,6 +50,12 @@ export async function ignores(): Promise<Linter.Config[]> {
'**/china.json', '**/china.json',
'**/.github', '**/.github',
'**/lefthook.yml', '**/lefthook.yml',
'**/.agent/**',
'**/.agents/**',
'**/.codex/**',
'**/.claude/**',
'**/.cursor/**',
], ],
}, },
]; ];

View File

@ -1,25 +0,0 @@
import type { Linter } from 'eslint';
import * as pluginImport from 'eslint-plugin-import-x';
export async function importPluginConfig(): Promise<Linter.Config[]> {
return [
{
plugins: {
// @ts-expect-error - This is a dynamic import
import: pluginImport,
},
rules: {
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'import/first': 'error',
'import/newline-after-import': 'error',
'import/no-duplicates': 'error',
'import/no-mutable-exports': 'error',
'import/no-named-default': 'error',
'import/no-self-import': 'error',
'import/no-unresolved': 'off',
'import/no-webpack-loader-syntax': 'error',
},
},
];
}

View File

@ -1,17 +1,12 @@
export * from './command'; export * from './command';
export * from './comments'; export * from './comments';
export * from './disableds';
export * from './ignores'; export * from './ignores';
export * from './import';
export * from './javascript'; export * from './javascript';
export * from './jsdoc';
export * from './jsonc'; export * from './jsonc';
export * from './node'; export * from './node';
export * from './oxlint';
export * from './perfectionist'; export * from './perfectionist';
export * from './pnpm'; export * from './pnpm';
export * from './prettier';
export * from './regexp';
export * from './test';
export * from './turbo'; export * from './turbo';
export * from './typescript'; export * from './typescript';
export * from './unicorn'; export * from './unicorn';

View File

@ -4,7 +4,73 @@ import js from '@eslint/js';
import pluginUnusedImports from 'eslint-plugin-unused-imports'; import pluginUnusedImports from 'eslint-plugin-unused-imports';
import globals from 'globals'; import globals from 'globals';
const rulesCoveredByOxlint = new Set([
'constructor-super',
'for-direction',
'getter-return',
'no-async-promise-executor',
'no-case-declarations',
'no-class-assign',
'no-compare-neg-zero',
'no-cond-assign',
'no-const-assign',
'no-constant-binary-expression',
'no-constant-condition',
'no-debugger',
'no-delete-var',
'no-dupe-args',
'no-dupe-class-members',
'no-dupe-else-if',
'no-dupe-keys',
'no-duplicate-case',
'no-empty',
'no-empty-character-class',
'no-empty-pattern',
'no-empty-static-block',
'no-ex-assign',
'no-extra-boolean-cast',
'no-fallthrough',
'no-func-assign',
'no-global-assign',
'no-import-assign',
'no-invalid-regexp',
'no-irregular-whitespace',
'no-loss-of-precision',
'no-misleading-character-class',
'no-new-native-nonconstructor',
'no-nonoctal-decimal-escape',
'no-obj-calls',
'no-prototype-builtins',
'no-redeclare',
'no-regex-spaces',
'no-self-assign',
'no-setter-return',
'no-shadow-restricted-names',
'no-sparse-arrays',
'no-this-before-super',
'no-unreachable',
'no-unsafe-finally',
'no-unsafe-negation',
'no-unsafe-optional-chaining',
'no-unused-labels',
'no-unused-private-class-members',
'no-unused-vars',
'no-useless-backreference',
'no-useless-catch',
'no-useless-escape',
'no-with',
'require-yield',
'use-isnan',
'valid-typeof',
]);
export async function javascript(): Promise<Linter.Config[]> { export async function javascript(): Promise<Linter.Config[]> {
const recommendedRules = Object.fromEntries(
Object.entries(js.configs.recommended.rules).filter(
([ruleName]) => !rulesCoveredByOxlint.has(ruleName),
),
);
return [ return [
{ {
languageOptions: { languageOptions: {
@ -33,79 +99,11 @@ export async function javascript(): Promise<Linter.Config[]> {
'unused-imports': pluginUnusedImports, 'unused-imports': pluginUnusedImports,
}, },
rules: { rules: {
...js.configs.recommended.rules, ...recommendedRules,
'accessor-pairs': [
'error',
{ enforceForClassMembers: true, setWithoutGet: true },
],
'array-callback-return': 'error',
'block-scoped-var': 'error',
'constructor-super': 'error',
'default-case-last': 'error',
'dot-notation': ['error', { allowKeywords: true }], 'dot-notation': ['error', { allowKeywords: true }],
eqeqeq: ['error', 'always'],
'keyword-spacing': 'off', 'keyword-spacing': 'off',
'new-cap': [
'error',
{ capIsNew: false, newIsCap: true, properties: true },
],
'no-alert': 'error',
'no-array-constructor': 'error',
'no-async-promise-executor': 'error',
'no-caller': 'error',
'no-case-declarations': 'error',
'no-class-assign': 'error',
'no-compare-neg-zero': 'error',
'no-cond-assign': ['error', 'always'],
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-const-assign': 'error',
'no-control-regex': 'error', 'no-control-regex': 'error',
'no-debugger': 'error',
'no-delete-var': 'error',
'no-dupe-args': 'error',
'no-dupe-class-members': 'error',
'no-dupe-keys': 'error',
'no-duplicate-case': 'error',
'no-empty': ['error', { allowEmptyCatch: true }],
'no-empty-character-class': 'error',
'no-empty-function': 'off', 'no-empty-function': 'off',
'no-empty-pattern': 'error',
'no-eval': 'error',
'no-ex-assign': 'error',
'no-extend-native': 'error',
'no-extra-bind': 'error',
'no-extra-boolean-cast': 'error',
'no-fallthrough': 'error',
'no-func-assign': 'error',
'no-global-assign': 'error',
'no-implied-eval': 'error',
'no-import-assign': 'error',
'no-invalid-regexp': 'error',
'no-irregular-whitespace': 'error',
'no-iterator': 'error',
'no-labels': ['error', { allowLoop: false, allowSwitch: false }],
'no-lone-blocks': 'error',
'no-loss-of-precision': 'error',
'no-misleading-character-class': 'error',
'no-multi-str': 'error',
'no-new': 'error',
'no-new-func': 'error',
'no-new-object': 'error',
'no-new-symbol': 'error',
'no-new-wrappers': 'error',
'no-obj-calls': 'error',
'no-octal': 'error',
'no-octal-escape': 'error',
'no-proto': 'error',
'no-prototype-builtins': 'error',
'no-redeclare': ['error', { builtinGlobals: false }],
'no-regex-spaces': 'error',
'no-restricted-globals': [
'error',
{ message: 'Use `globalThis` instead.', name: 'global' },
{ message: 'Use `globalThis` instead.', name: 'self' },
],
'no-restricted-properties': [ 'no-restricted-properties': [
'error', 'error',
{ {
@ -138,84 +136,9 @@ export async function javascript(): Promise<Linter.Config[]> {
'TSEnumDeclaration[const=true]', 'TSEnumDeclaration[const=true]',
'TSExportAssignment', 'TSExportAssignment',
], ],
'no-self-assign': ['error', { props: true }],
'no-self-compare': 'error',
'no-sequences': 'error',
'no-shadow-restricted-names': 'error',
'no-sparse-arrays': 'error',
'no-template-curly-in-string': 'error',
'no-this-before-super': 'error',
'no-throw-literal': 'error',
'no-undef': 'off', 'no-undef': 'off',
'no-undef-init': 'error',
'no-unexpected-multiline': 'error',
'no-unmodified-loop-condition': 'error',
'no-unneeded-ternary': ['error', { defaultAssignment: false }],
'no-unreachable': 'error',
'no-unreachable-loop': 'error', 'no-unreachable-loop': 'error',
'no-unsafe-finally': 'error',
'no-unsafe-negation': 'error',
'no-unused-expressions': [
'error',
{
allowShortCircuit: true,
allowTaggedTemplates: true,
allowTernary: true,
},
],
'no-unused-vars': [
'error',
{
args: 'none',
caughtErrors: 'none',
ignoreRestSiblings: true,
vars: 'all',
},
],
'no-use-before-define': [
'error',
{ classes: false, functions: false, variables: false },
],
'no-useless-backreference': 'error',
'no-useless-call': 'error',
'no-useless-catch': 'error',
'no-useless-computed-key': 'error',
'no-useless-constructor': 'error',
'no-useless-rename': 'error',
'no-useless-return': 'error',
'no-var': 'error',
'no-with': 'error',
'object-shorthand': [
'error',
'always',
{ avoidQuotes: true, ignoreConstructors: false },
],
'one-var': ['error', { initialized: 'never' }],
'prefer-arrow-callback': [
'error',
{
allowNamedFunctions: false,
allowUnboundThis: true,
},
],
'prefer-const': [
'error',
{
destructuring: 'all',
ignoreReadBeforeAssign: true,
},
],
'prefer-exponentiation-operator': 'error',
'prefer-promise-reject-errors': 'error',
'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }],
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'prefer-template': 'error',
'space-before-function-paren': 'off', 'space-before-function-paren': 'off',
'spaced-comment': 'error',
'symbol-description': 'error',
'unicode-bom': ['error', 'never'],
'unused-imports/no-unused-imports': 'error', 'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [ 'unused-imports/no-unused-vars': [
@ -227,14 +150,6 @@ export async function javascript(): Promise<Linter.Config[]> {
varsIgnorePattern: '^_', varsIgnorePattern: '^_',
}, },
], ],
'use-isnan': [
'error',
{ enforceForIndexOf: true, enforceForSwitchCase: true },
],
'valid-typeof': ['error', { requireStringLiterals: true }],
'vars-on-top': 'error',
yoda: ['error', 'never'],
}, },
}, },
]; ];

View File

@ -1,34 +0,0 @@
import type { Linter } from 'eslint';
import { interopDefault } from '../util';
export async function jsdoc(): Promise<Linter.Config[]> {
const [pluginJsdoc] = await Promise.all([
interopDefault(import('eslint-plugin-jsdoc')),
] as const);
return [
{
plugins: {
jsdoc: pluginJsdoc,
},
rules: {
'jsdoc/check-access': 'warn',
'jsdoc/check-param-names': 'warn',
'jsdoc/check-property-names': 'warn',
'jsdoc/check-types': 'warn',
'jsdoc/empty-tags': 'warn',
'jsdoc/implements-on-classes': 'warn',
'jsdoc/no-defaults': 'warn',
'jsdoc/no-multi-asterisks': 'warn',
'jsdoc/require-param-name': 'warn',
'jsdoc/require-property': 'warn',
'jsdoc/require-property-description': 'warn',
'jsdoc/require-property-name': 'warn',
'jsdoc/require-returns-check': 'warn',
'jsdoc/require-returns-description': 'warn',
'jsdoc/require-yields-check': 'warn',
},
},
];
}

View File

@ -3,17 +3,12 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
export async function jsonc(): Promise<Linter.Config[]> { export async function jsonc(): Promise<Linter.Config[]> {
const [pluginJsonc, parserJsonc] = await Promise.all([ const pluginJsonc = await interopDefault(import('eslint-plugin-jsonc'));
interopDefault(import('eslint-plugin-jsonc')),
interopDefault(import('jsonc-eslint-parser')),
] as const);
return [ return [
{ {
files: ['**/*.json', '**/*.json5', '**/*.jsonc', '*.code-workspace'], files: ['**/*.json', '**/*.json5', '**/*.jsonc', '*.code-workspace'],
languageOptions: { language: 'jsonc/x',
parser: parserJsonc as any,
},
plugins: { plugins: {
jsonc: pluginJsonc as any, jsonc: pluginJsonc as any,
}, },

View File

@ -13,7 +13,6 @@ export async function node(): Promise<Linter.Config[]> {
rules: { rules: {
'n/handle-callback-err': ['error', '^(err|error)$'], 'n/handle-callback-err': ['error', '^(err|error)$'],
'n/no-deprecated-api': 'error', 'n/no-deprecated-api': 'error',
'n/no-exports-assign': 'error',
'n/no-extraneous-import': [ 'n/no-extraneous-import': [
'error', 'error',
{ {
@ -23,13 +22,10 @@ export async function node(): Promise<Linter.Config[]> {
'vitest', 'vitest',
'vite', 'vite',
'@vue/test-utils', '@vue/test-utils',
'@vben/tailwind-config',
'@playwright/test', '@playwright/test',
], ],
}, },
], ],
'n/no-new-require': 'error',
'n/no-path-concat': 'error',
// 'n/no-unpublished-import': 'off', // 'n/no-unpublished-import': 'off',
'n/no-unsupported-features/es-syntax': [ 'n/no-unsupported-features/es-syntax': [
'error', 'error',
@ -44,6 +40,33 @@ export async function node(): Promise<Linter.Config[]> {
'n/process-exit-as-throw': 'error', 'n/process-exit-as-throw': 'error',
}, },
}, },
{
files: [
'**/__tests__/**/*.?([cm])[jt]s?(x)',
'**/*.spec.?([cm])[jt]s?(x)',
'**/*.test.?([cm])[jt]s?(x)',
'**/*.bench.?([cm])[jt]s?(x)',
'**/*.benchmark.?([cm])[jt]s?(x)',
],
rules: {
'n/prefer-global/process': 'off',
},
},
{
files: ['apps/backend-mock/**/**', 'docs/**/**'],
rules: {
'n/no-extraneous-import': 'off',
'n/prefer-global/buffer': 'off',
'n/prefer-global/process': 'off',
},
},
{
files: ['**/**/playwright.config.ts'],
rules: {
'n/prefer-global/buffer': 'off',
'n/prefer-global/process': 'off',
},
},
{ {
files: [ files: [
'scripts/**/*.?([cm])[jt]s?(x)', 'scripts/**/*.?([cm])[jt]s?(x)',

View File

@ -0,0 +1,13 @@
import type { Linter } from 'eslint';
import { mergeOxlintConfigs, oxlintConfig } from '@vben/oxlint-config';
import oxlint from 'eslint-plugin-oxlint';
export async function oxcCompat(): Promise<Linter.Config[]> {
const { extends: _extends, ...config } = mergeOxlintConfigs(oxlintConfig);
return oxlint.buildFromOxlintConfig(
config as Parameters<typeof oxlint.buildFromOxlintConfig>[0],
);
}

View File

@ -21,41 +21,58 @@ export async function perfectionist(): Promise<Linter.Config[]> {
'perfectionist/sort-imports': [ 'perfectionist/sort-imports': [
'error', 'error',
{ {
customGroups: { customGroups: [
type: { {
'vben-core-type': ['^@vben-core/.+'], selector: 'type',
'vben-type': ['^@vben/.+'], groupName: 'vben-core-type',
'vue-type': ['^vue$', '^vue-.+', '^@vue/.+'], elementNamePattern: '^@vben-core/.+',
}, },
value: { {
vben: ['^@vben/.+'], selector: 'type',
'vben-core': ['^@vben-core/.+'], groupName: 'vben-type',
vue: ['^vue$', '^vue-.+', '^@vue/.+'], elementNamePattern: '^@vben/.+',
}, },
}, {
selector: 'type',
groupName: 'vue-type',
elementNamePattern: ['^vue$', '^vue-.+', '^@vue/.+'],
},
{
groupName: 'vben',
elementNamePattern: '^@vben/.+',
},
{
groupName: 'vben-core',
elementNamePattern: '^@vben-core/.+',
},
{
groupName: 'vue',
elementNamePattern: ['^vue$', '^vue-.+', '^@vue/.+'],
},
],
environment: 'node', environment: 'node',
groups: [ groups: [
['external-type', 'builtin-type', 'type'], ['type-external', 'type-builtin', 'type-import'],
'vue-type', 'vue-type',
'vben-type', 'vben-type',
'vben-core-type', 'vben-core-type',
['parent-type', 'sibling-type', 'index-type'], ['type-parent', 'type-sibling', 'type-index'],
['internal-type'], ['type-internal'],
'builtin', 'value-builtin',
'vue', 'vue',
'vben', 'vben',
'vben-core', 'vben-core',
'external', 'value-external',
'internal', 'value-internal',
['parent', 'sibling', 'index'], ['value-parent', 'value-sibling', 'value-index'],
'side-effect', 'side-effect',
'side-effect-style', 'side-effect-style',
'style', 'style',
'object', 'ts-equals-import',
'unknown', 'unknown',
], ],
internalPattern: ['^#/.+'], internalPattern: ['^#/.+'],
newlinesBetween: 'always', newlinesBetween: 1,
order: 'asc', order: 'asc',
type: 'natural', type: 'natural',
}, },

View File

@ -3,18 +3,15 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
export async function pnpm(): Promise<Linter.Config[]> { export async function pnpm(): Promise<Linter.Config[]> {
const [pluginPnpm, parserPnpm, parserJsonc] = await Promise.all([ const [pluginPnpm, parserPnpm] = await Promise.all([
interopDefault(import('eslint-plugin-pnpm')), interopDefault(import('eslint-plugin-pnpm')),
interopDefault(import('yaml-eslint-parser')), interopDefault(import('yaml-eslint-parser')),
interopDefault(import('jsonc-eslint-parser')),
] as const); ] as const);
return [ return [
{ {
files: ['package.json', '**/package.json'], files: ['package.json', '**/package.json'],
languageOptions: { language: 'jsonc/x',
parser: parserJsonc,
},
plugins: { plugins: {
pnpm: pluginPnpm, pnpm: pluginPnpm,
}, },

View File

@ -1,19 +0,0 @@
import type { Linter } from 'eslint';
import { interopDefault } from '../util';
export async function prettier(): Promise<Linter.Config[]> {
const [pluginPrettier] = await Promise.all([
interopDefault(import('eslint-plugin-prettier')),
] as const);
return [
{
plugins: {
prettier: pluginPrettier,
},
rules: {
'prettier/prettier': 'error',
},
},
];
}

View File

@ -1,20 +0,0 @@
import type { Linter } from 'eslint';
import { interopDefault } from '../util';
export async function regexp(): Promise<Linter.Config[]> {
const [pluginRegexp] = await Promise.all([
interopDefault(import('eslint-plugin-regexp')),
] as const);
return [
{
plugins: {
regexp: pluginRegexp,
},
rules: {
...pluginRegexp.configs.recommended.rules,
},
},
];
}

View File

@ -1,45 +0,0 @@
import type { Linter } from 'eslint';
import { interopDefault } from '../util';
export async function test(): Promise<Linter.Config[]> {
const [pluginTest, pluginNoOnlyTests] = await Promise.all([
interopDefault(import('eslint-plugin-vitest')),
// @ts-expect-error - no types
interopDefault(import('eslint-plugin-no-only-tests')),
] as const);
return [
{
files: [
`**/__tests__/**/*.?([cm])[jt]s?(x)`,
`**/*.spec.?([cm])[jt]s?(x)`,
`**/*.test.?([cm])[jt]s?(x)`,
`**/*.bench.?([cm])[jt]s?(x)`,
`**/*.benchmark.?([cm])[jt]s?(x)`,
],
plugins: {
test: {
...pluginTest,
rules: {
...pluginTest.rules,
...pluginNoOnlyTests.rules,
},
},
},
rules: {
'no-console': 'off',
'node/prefer-global/process': 'off',
'test/consistent-test-it': [
'error',
{ fn: 'it', withinDescribe: 'it' },
],
'test/no-identical-title': 'error',
'test/no-import-node-test': 'error',
'test/no-only-tests': 'error',
'test/prefer-hooks-in-order': 'error',
'test/prefer-lowercase-title': 'error',
},
},
];
}

View File

@ -3,9 +3,7 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
export async function turbo(): Promise<Linter.Config[]> { export async function turbo(): Promise<Linter.Config[]> {
const [pluginTurbo] = await Promise.all([ const pluginTurbo = await interopDefault(import('eslint-config-turbo'));
interopDefault(import('eslint-config-turbo')),
] as const);
return [ return [
{ {

View File

@ -2,11 +2,24 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
const rulesCoveredByOxlint = new Set([
'@typescript-eslint/ban-ts-comment',
'@typescript-eslint/no-non-null-assertion',
'@typescript-eslint/no-unused-expressions',
'@typescript-eslint/no-unused-vars',
'@typescript-eslint/triple-slash-reference',
]);
export async function typescript(): Promise<Linter.Config[]> { export async function typescript(): Promise<Linter.Config[]> {
const [pluginTs, parserTs] = await Promise.all([ const [pluginTs, parserTs] = await Promise.all([
interopDefault(import('@typescript-eslint/eslint-plugin')), interopDefault(import('@typescript-eslint/eslint-plugin')),
interopDefault(import('@typescript-eslint/parser')), interopDefault(import('@typescript-eslint/parser')),
] as const); ] as const);
const strictRules = Object.fromEntries(
Object.entries(pluginTs.configs.strict?.rules ?? {}).filter(
([ruleName]) => !rulesCoveredByOxlint.has(ruleName),
),
);
return [ return [
{ {
@ -30,40 +43,14 @@ export async function typescript(): Promise<Linter.Config[]> {
}, },
rules: { rules: {
...pluginTs.configs['eslint-recommended']?.overrides?.[0]?.rules, ...pluginTs.configs['eslint-recommended']?.overrides?.[0]?.rules,
...pluginTs.configs.strict?.rules, ...strictRules,
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-check': false,
'ts-expect-error': 'allow-with-description',
'ts-ignore': 'allow-with-description',
'ts-nocheck': 'allow-with-description',
},
],
// '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'], // '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
'@typescript-eslint/consistent-type-definitions': 'off', '@typescript-eslint/consistent-type-definitions': 'off',
'@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-empty-function': [
'error',
{
allow: ['arrowFunctions', 'functions', 'methods'],
},
],
'@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-namespace': 'off', '@typescript-eslint/no-namespace': 'off',
'@typescript-eslint/no-non-null-assertion': 'error',
'@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/no-var-requires': 'error',
'unused-imports/no-unused-vars': 'off', 'unused-imports/no-unused-vars': 'off',
}, },
}, },

View File

@ -2,10 +2,20 @@ import type { Linter } from 'eslint';
import { interopDefault } from '../util'; import { interopDefault } from '../util';
const rulesCoveredByOxlint = new Set([
'unicorn/consistent-function-scoping',
'unicorn/no-process-exit',
'unicorn/prefer-global-this',
'unicorn/prefer-module',
]);
export async function unicorn(): Promise<Linter.Config[]> { export async function unicorn(): Promise<Linter.Config[]> {
const [pluginUnicorn] = await Promise.all([ const pluginUnicorn = await interopDefault(import('eslint-plugin-unicorn'));
interopDefault(import('eslint-plugin-unicorn')), const recommendedRules = Object.fromEntries(
] as const); Object.entries(pluginUnicorn.configs.recommended.rules ?? {}).filter(
([ruleName]) => !rulesCoveredByOxlint.has(ruleName),
),
);
return [ return [
{ {
@ -13,11 +23,10 @@ export async function unicorn(): Promise<Linter.Config[]> {
unicorn: pluginUnicorn, unicorn: pluginUnicorn,
}, },
rules: { rules: {
...pluginUnicorn.configs.recommended.rules, ...recommendedRules,
'unicorn/better-regex': 'off', 'unicorn/better-regex': 'off',
'unicorn/consistent-destructuring': 'off', 'unicorn/consistent-destructuring': 'off',
'unicorn/consistent-function-scoping': 'off',
'unicorn/expiring-todo-comments': 'off', 'unicorn/expiring-todo-comments': 'off',
'unicorn/filename-case': 'off', 'unicorn/filename-case': 'off',
'unicorn/import-style': 'off', 'unicorn/import-style': 'off',
@ -27,19 +36,9 @@ export async function unicorn(): Promise<Linter.Config[]> {
'unicorn/prefer-at': 'off', 'unicorn/prefer-at': 'off',
'unicorn/prefer-dom-node-text-content': 'off', 'unicorn/prefer-dom-node-text-content': 'off',
'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }], 'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }],
'unicorn/prefer-global-this': 'off',
'unicorn/prefer-top-level-await': 'off', 'unicorn/prefer-top-level-await': 'off',
'unicorn/prevent-abbreviations': 'off', 'unicorn/prevent-abbreviations': 'off',
}, },
}, },
{
files: [
'scripts/**/*.?([cm])[jt]s?(x)',
'internal/**/*.?([cm])[jt]s?(x)',
],
rules: {
'unicorn/no-process-exit': 'off',
},
},
]; ];
} }

View File

@ -128,7 +128,6 @@ export async function vue(): Promise<Linter.Config[]> {
}, },
], ],
'vue/one-component-per-file': 'error', 'vue/one-component-per-file': 'error',
'vue/prefer-import-from-vue': 'error',
'vue/prefer-separate-static-class': 'error', 'vue/prefer-separate-static-class': 'error',
'vue/prefer-template': 'error', 'vue/prefer-template': 'error',
'vue/prop-name-casing': ['error', 'camelCase'], 'vue/prop-name-casing': ['error', 'camelCase'],

View File

@ -12,7 +12,7 @@ export async function yaml(): Promise<Linter.Config[]> {
{ {
files: ['**/*.y?(a)ml'], files: ['**/*.y?(a)ml'],
plugins: { plugins: {
yaml: pluginYaml as any, yaml: pluginYaml,
}, },
languageOptions: { languageOptions: {
parser: parserYaml, parser: parserYaml,

View File

@ -1,10 +1,6 @@
import type { Linter } from 'eslint'; import type { Linter } from 'eslint';
const restrictedImportIgnores = [ const restrictedImportIgnores = ['**/vite.config.mts'];
'**/vite.config.mts',
'**/tailwind.config.mjs',
'**/postcss.config.mjs',
];
const customConfig: Linter.Config[] = [ const customConfig: Linter.Config[] = [
// shadcn-ui 内部组件是自动生成的,不做太多限制 // shadcn-ui 内部组件是自动生成的,不做太多限制
@ -25,14 +21,6 @@ const customConfig: Linter.Config[] = [
ignores: restrictedImportIgnores, ignores: restrictedImportIgnores,
rules: { rules: {
'perfectionist/sort-interfaces': 'off', 'perfectionist/sort-interfaces': 'off',
'perfectionist/sort-objects': 'off',
},
},
{
files: ['**/**.vue'],
ignores: restrictedImportIgnores,
rules: {
'perfectionist/sort-objects': 'off',
}, },
}, },
{ {
@ -67,7 +55,6 @@ const customConfig: Linter.Config[] = [
], ],
}, },
], ],
'perfectionist/sort-interfaces': 'off',
}, },
}, },
{ {
@ -141,19 +128,12 @@ const customConfig: Linter.Config[] = [
{ {
files: ['docs/**/**'], files: ['docs/**/**'],
rules: { rules: {
'@typescript-eslint/no-extraneous-class': 'off',
'n/no-extraneous-import': 'off',
'n/prefer-global/buffer': 'off',
'n/prefer-global/process': 'off',
'no-console': 'off', 'no-console': 'off',
'unicorn/prefer-module': 'off',
}, },
}, },
{ {
files: ['**/**/playwright.config.ts'], files: ['**/**/playwright.config.ts'],
rules: { rules: {
'n/prefer-global/buffer': 'off',
'n/prefer-global/process': 'off',
'no-console': 'off', 'no-console': 'off',
}, },
}, },

View File

@ -3,18 +3,13 @@ import type { Linter } from 'eslint';
import { import {
command, command,
comments, comments,
disableds,
ignores, ignores,
importPluginConfig,
javascript, javascript,
jsdoc,
jsonc, jsonc,
node, node,
oxcCompat,
perfectionist, perfectionist,
pnpm, pnpm,
prettier,
regexp,
test,
turbo, turbo,
typescript, typescript,
unicorn, unicorn,
@ -36,23 +31,18 @@ async function defineConfig(config: FlatConfig[] = []) {
vue(), vue(),
javascript(), javascript(),
ignores(), ignores(),
prettier(),
typescript(), typescript(),
jsonc(), jsonc(),
disableds(),
importPluginConfig(),
node(), node(),
perfectionist(), perfectionist(),
comments(), comments(),
jsdoc(),
unicorn(), unicorn(),
test(),
regexp(),
command(), command(),
turbo(), turbo(),
yaml(), yaml(),
pnpm(), pnpm(),
...customConfig, ...customConfig,
oxcCompat(),
...config, ...config,
]; ];

View File

@ -3,8 +3,5 @@ import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({ export default defineBuildConfig({
clean: true, clean: true,
declaration: true, declaration: true,
entries: ['src/index', './src/postcss.config'], entries: ['src/index'],
rollup: {
emitCJS: true,
},
}); });

View File

@ -1,28 +1,32 @@
{ {
"name": "@vben/prettier-config", "name": "@vben/oxfmt-config",
"version": "5.6.0", "version": "5.7.0",
"private": true, "private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin", "homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", "bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
"directory": "internal/lint-configs/prettier-config" "directory": "internal/lint-configs/oxfmt-config"
}, },
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",
"scripts": {
"stub": "pnpm unbuild --stub"
},
"files": [ "files": [
"dist" "dist"
], ],
"main": "./index.mjs", "main": "./dist/index.mjs",
"module": "./index.mjs", "module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": { "exports": {
".": { ".": {
"default": "./index.mjs" "types": "./dist/index.d.ts",
"import": "./dist/index.mjs"
} }
}, },
"dependencies": { "dependencies": {
"prettier": "catalog:", "oxfmt": "catalog:"
"prettier-plugin-tailwindcss": "catalog:"
} }
} }

View File

@ -0,0 +1,22 @@
import { defineConfig as defineOxfmtConfig } from 'oxfmt';
type OxfmtConfig = Parameters<typeof defineOxfmtConfig>[0];
const oxfmtConfig = defineOxfmtConfig({
printWidth: 80,
proseWrap: 'never',
semi: true,
singleQuote: true,
sortPackageJson: false,
trailingComma: 'all',
});
function defineConfig(config: OxfmtConfig = {}) {
return defineOxfmtConfig({
...oxfmtConfig,
...config,
});
}
export { defineConfig, oxfmtConfig };
export type { OxfmtConfig };

View File

@ -0,0 +1,7 @@
import { defineBuildConfig } from 'unbuild';
export default defineBuildConfig({
clean: true,
declaration: true,
entries: ['src/index'],
});

View File

@ -0,0 +1,33 @@
{
"name": "@vben/oxlint-config",
"version": "5.7.0",
"private": true,
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
"type": "git",
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
"directory": "internal/lint-configs/oxlint-config"
},
"license": "MIT",
"type": "module",
"scripts": {
"stub": "pnpm unbuild --stub"
},
"files": [
"dist"
],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs"
}
},
"dependencies": {
"eslint-plugin-better-tailwindcss": "catalog:",
"oxlint": "catalog:"
}
}

View File

@ -0,0 +1,17 @@
import type { OxlintConfig } from 'oxlint';
const ignores: OxlintConfig = {
ignorePatterns: [
'**/dist/**',
'**/node_modules/**',
'docs/**',
'playground/public/**',
'**/*.json',
'**/*.md',
'**/*.svg',
'**/*.yaml',
'**/*.yml',
],
};
export { ignores };

View File

@ -0,0 +1,18 @@
import type { OxlintConfig } from 'oxlint';
const importPluginConfig: OxlintConfig = {
rules: {
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'import/first': 'error',
'import/no-duplicates': 'error',
'import/no-mutable-exports': 'error',
'import/no-named-as-default': 'off',
'import/no-named-as-default-member': 'off',
'import/no-named-default': 'error',
'import/no-self-import': 'error',
'import/no-unassigned-import': 'off',
'import/no-webpack-loader-syntax': 'error',
},
};
export { importPluginConfig };

View File

@ -0,0 +1,90 @@
import type { OxlintConfig } from 'oxlint';
import { defineConfig as defineOxlintConfig } from 'oxlint';
import { ignores } from './ignores';
import { importPluginConfig } from './import';
import { javascript } from './javascript';
import { node } from './node';
import { overrides } from './overrides';
import { plugins } from './plugins';
import { tailwindcss } from './tailwindcss';
import { test } from './test';
import { typescript } from './typescript';
import { unicorn } from './unicorn';
import { vue } from './vue';
function mergeOxlintConfigs(...configs: OxlintConfig[]): OxlintConfig {
const merged: OxlintConfig = {};
for (const config of configs) {
merged.categories =
merged.categories && config.categories
? { ...merged.categories, ...config.categories }
: (config.categories ?? merged.categories);
merged.env =
merged.env && config.env
? { ...merged.env, ...config.env }
: (config.env ?? merged.env);
merged.globals =
merged.globals && config.globals
? { ...merged.globals, ...config.globals }
: (config.globals ?? merged.globals);
merged.ignorePatterns = [
...(merged.ignorePatterns ?? []),
...(config.ignorePatterns ?? []),
];
merged.jsPlugins = [
...new Set([...(merged.jsPlugins ?? []), ...(config.jsPlugins ?? [])]),
];
merged.overrides = [
...(merged.overrides ?? []),
...(config.overrides ?? []),
];
merged.plugins = [
...new Set([...(merged.plugins ?? []), ...(config.plugins ?? [])]),
];
merged.rules =
merged.rules && config.rules
? { ...merged.rules, ...config.rules }
: (config.rules ?? merged.rules);
merged.settings =
merged.settings && config.settings
? { ...merged.settings, ...config.settings }
: (config.settings ?? merged.settings);
}
return merged;
}
const oxlintConfig = defineOxlintConfig(
mergeOxlintConfigs(
javascript,
ignores,
plugins,
importPluginConfig,
node,
overrides,
tailwindcss,
test,
typescript,
unicorn,
vue,
),
);
export {
ignores,
importPluginConfig,
javascript,
mergeOxlintConfigs,
node,
overrides,
oxlintConfig,
plugins,
tailwindcss,
test,
typescript,
unicorn,
vue,
};

View File

@ -0,0 +1,156 @@
import type { OxlintConfig } from 'oxlint';
const javascript: OxlintConfig = {
categories: {
correctness: 'error',
suspicious: 'warn',
},
env: {
browser: true,
es2021: true,
node: true,
},
globals: {
document: 'readonly',
navigator: 'readonly',
window: 'readonly',
},
rules: {
'accessor-pairs': [
'error',
{
enforceForClassMembers: true,
setWithoutGet: true,
},
],
'array-callback-return': 'error',
'block-scoped-var': 'error',
'default-case-last': 'error',
eqeqeq: ['error', 'always'],
'eslint/no-unreachable': 'error',
'new-cap': [
'error',
{
capIsNew: false,
newIsCap: true,
properties: true,
},
],
'no-alert': 'error',
'no-array-constructor': 'error',
'no-caller': 'error',
'no-case-declarations': 'error',
'no-console': ['error', { allow: ['warn', 'error'] }],
'no-control-regex': 'off',
'no-debugger': 'error',
'no-empty': ['error', { allowEmptyCatch: true }],
'no-fallthrough': 'error',
'no-new-func': 'error',
'no-new-object': 'error',
'no-new-symbol': 'error',
'no-labels': ['error', { allowLoop: false, allowSwitch: false }],
'no-lone-blocks': 'error',
'no-multi-str': 'error',
'no-octal': 'error',
'no-octal-escape': 'error',
'no-proto': 'error',
'no-prototype-builtins': 'error',
'no-redeclare': ['error', { builtinGlobals: false }],
'no-regex-spaces': 'error',
'no-self-compare': 'error',
'no-sequences': 'error',
'no-shadow': 'off',
'no-shadow-restricted-names': 'error',
'eslint/no-empty-function': [
'error',
{
allow: ['arrowFunctions', 'functions', 'methods'],
},
],
'no-template-curly-in-string': 'error',
'no-throw-literal': 'error',
'no-undef-init': 'error',
'no-unused-expressions': [
'error',
{
allowShortCircuit: true,
allowTaggedTemplates: true,
allowTernary: true,
},
],
'eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'no-var': 'error',
'no-eval': 'error',
'no-iterator': 'error',
'no-new-wrappers': 'error',
'no-restricted-globals': [
'error',
{ message: 'Use `globalThis` instead.', name: 'global' },
{ message: 'Use `globalThis` instead.', name: 'self' },
],
'no-useless-call': 'error',
'no-useless-computed-key': 'error',
'no-useless-constructor': 'error',
'no-useless-return': 'error',
'object-shorthand': [
'error',
'always',
{
avoidQuotes: true,
ignoreConstructors: false,
},
],
'one-var': ['error', { initialized: 'never' }],
'prefer-const': [
'error',
{
destructuring: 'all',
ignoreReadBeforeAssign: true,
},
],
'eslint/prefer-arrow-callback': [
'error',
{
allowNamedFunctions: false,
allowUnboundThis: true,
},
],
'prefer-exponentiation-operator': 'error',
'prefer-promise-reject-errors': 'error',
'eslint/prefer-regex-literals': [
'error',
{
disallowRedundantWrapping: true,
},
],
'prefer-rest-params': 'error',
'prefer-spread': 'error',
'prefer-template': 'error',
'spaced-comment': 'error',
'symbol-description': 'error',
'unicode-bom': ['error', 'never'],
'use-isnan': [
'error',
{
enforceForIndexOf: true,
enforceForSwitchCase: true,
},
],
'valid-typeof': [
'error',
{
requireStringLiterals: true,
},
],
'vars-on-top': 'error',
yoda: ['error', 'never'],
},
};
export { javascript };

View File

@ -0,0 +1,11 @@
import type { OxlintConfig } from 'oxlint';
const node: OxlintConfig = {
rules: {
'node/no-exports-assign': 'error',
'node/no-new-require': 'error',
'node/no-path-concat': 'error',
},
};
export { node };

View File

@ -0,0 +1,98 @@
import type { OxlintConfig } from 'oxlint';
const overrides: OxlintConfig = {
overrides: [
{
files: ['*.d.ts', '**/*.d.ts'],
rules: {
'import/no-unassigned-import': 'off',
'typescript/triple-slash-reference': 'off',
},
},
{
files: [
'**/__tests__/**/*.js',
'**/__tests__/**/*.cjs',
'**/__tests__/**/*.mjs',
'**/__tests__/**/*.jsx',
'**/__tests__/**/*.ts',
'**/__tests__/**/*.cts',
'**/__tests__/**/*.mts',
'**/__tests__/**/*.tsx',
'**/*.spec.js',
'**/*.spec.cjs',
'**/*.spec.mjs',
'**/*.spec.jsx',
'**/*.spec.ts',
'**/*.spec.cts',
'**/*.spec.mts',
'**/*.spec.tsx',
'**/*.test.js',
'**/*.test.cjs',
'**/*.test.mjs',
'**/*.test.jsx',
'**/*.test.ts',
'**/*.test.cts',
'**/*.test.mts',
'**/*.test.tsx',
'**/*.bench.js',
'**/*.bench.cjs',
'**/*.bench.mjs',
'**/*.bench.jsx',
'**/*.bench.ts',
'**/*.bench.cts',
'**/*.bench.mts',
'**/*.bench.tsx',
'**/*.benchmark.js',
'**/*.benchmark.cjs',
'**/*.benchmark.mjs',
'**/*.benchmark.jsx',
'**/*.benchmark.ts',
'**/*.benchmark.cts',
'**/*.benchmark.mts',
'**/*.benchmark.tsx',
],
rules: {
'no-console': 'off',
},
},
{
files: ['packages/@core/base/shared/src/utils/inference.ts'],
rules: {
'vue/prefer-import-from-vue': 'off',
},
},
{
files: ['packages/@core/ui-kit/menu-ui/src/sub-menu.vue'],
rules: {
'import/no-self-import': 'off',
},
},
{
files: [
'scripts/**/*.js',
'scripts/**/*.cjs',
'scripts/**/*.mjs',
'scripts/**/*.jsx',
'scripts/**/*.ts',
'scripts/**/*.cts',
'scripts/**/*.mts',
'scripts/**/*.tsx',
'internal/**/*.js',
'internal/**/*.cjs',
'internal/**/*.mjs',
'internal/**/*.jsx',
'internal/**/*.ts',
'internal/**/*.cts',
'internal/**/*.mts',
'internal/**/*.tsx',
],
rules: {
'no-console': 'off',
'unicorn/no-process-exit': 'off',
},
},
],
};
export { overrides };

View File

@ -0,0 +1,7 @@
import type { OxlintConfig } from 'oxlint';
const plugins: OxlintConfig = {
plugins: ['import', 'node', 'oxc', 'typescript', 'unicorn', 'vitest', 'vue'],
};
export { plugins };

View File

@ -0,0 +1,50 @@
import type { OxlintConfig } from 'oxlint';
import eslintPluginBetterTailwindcss from 'eslint-plugin-better-tailwindcss';
import { getDefaultSelectors } from 'eslint-plugin-better-tailwindcss/defaults';
import { SelectorKind } from 'eslint-plugin-better-tailwindcss/types';
const selectors = [
...getDefaultSelectors(),
{
kind: SelectorKind.Attribute,
match: [{ type: 'objectValues' }],
name: '^classNames$',
},
];
const settings = {
entryPoint: 'packages/@core/base/design/src/css/global.css',
selectors,
};
const tailwindcss: OxlintConfig = {
// Generated shadcn-ui internals are intentionally left unmanaged.
ignorePatterns: ['packages/@core/ui-kit/shadcn-ui/**/*'],
jsPlugins: [
{
name: 'better-tailwindcss',
specifier: 'eslint-plugin-better-tailwindcss',
},
],
rules: {
...eslintPluginBetterTailwindcss.configs.recommended.rules,
'better-tailwindcss/enforce-consistent-class-order': [
'error',
{
detectComponentClasses: true,
unknownClassOrder: 'asc',
unknownClassPosition: 'start',
},
],
// Let Prettier own wrapping decisions to avoid ping-pong formatting.
'better-tailwindcss/enforce-consistent-line-wrapping': 'off',
'better-tailwindcss/no-unknown-classes': 'off',
},
settings: {
'better-tailwindcss': settings,
'eslint-plugin-better-tailwindcss': settings,
},
};
export { tailwindcss };

View File

@ -0,0 +1,23 @@
import type { OxlintConfig } from 'oxlint';
const test: OxlintConfig = {
rules: {
'jest/no-conditional-expect': 'off',
'jest/require-to-throw-message': 'off',
'vitest/consistent-test-it': [
'error',
{
fn: 'it',
withinDescribe: 'it',
},
],
'vitest/hoisted-apis-on-top': 'off',
'vitest/no-focused-tests': 'error',
'vitest/no-identical-title': 'error',
'vitest/no-import-node-test': 'error',
'vitest/prefer-hooks-in-order': 'error',
'vitest/prefer-lowercase-title': 'error',
},
};
export { test };

View File

@ -0,0 +1,28 @@
import type { OxlintConfig } from 'oxlint';
const typescript: OxlintConfig = {
rules: {
'typescript/ban-ts-comment': 'error',
// Keep the first type-aware rollout conservative. These rules currently
// produce high-volume diagnostics and need file-by-file cleanup later.
'typescript/await-thenable': 'off',
'typescript/no-base-to-string': 'off',
'typescript/no-duplicate-type-constituents': 'off',
'typescript/no-floating-promises': 'off',
'typescript/no-misused-spread': 'off',
'typescript/no-non-null-assertion': 'error',
'typescript/no-redundant-type-constituents': 'off',
'typescript/no-unnecessary-boolean-literal-compare': 'off',
'typescript/no-unnecessary-type-assertion': 'off',
'typescript/no-unnecessary-type-arguments': 'off',
'typescript/no-unnecessary-template-expression': 'off',
'typescript/no-unsafe-enum-comparison': 'off',
'typescript/no-unsafe-type-assertion': 'off',
'typescript/no-var-requires': 'error',
'typescript/restrict-template-expressions': 'off',
'typescript/triple-slash-reference': 'error',
'typescript/unbound-method': 'off',
},
};
export { typescript };

View File

@ -0,0 +1,14 @@
import type { OxlintConfig } from 'oxlint';
const unicorn: OxlintConfig = {
rules: {
'unicorn/consistent-function-scoping': 'off',
'unicorn/no-process-exit': 'error',
'unicorn/no-single-promise-in-promise-methods': 'off',
'unicorn/no-useless-spread': 'off',
'unicorn/prefer-global-this': 'off',
'unicorn/prefer-module': 'error',
},
};
export { unicorn };

Some files were not shown because too many files have changed in this diff Show More