Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

View file

@ -0,0 +1,235 @@
import { isPackageExists } from 'local-pkg';
import { e as ensurePackages, i as interopDefault, p as parserPlain } from '../shared/eslint-config.CePp8IWi.mjs';
import { b as GLOB_CSS, c as GLOB_POSTCSS, d as GLOB_SCSS, e as GLOB_LESS, f as GLOB_HTML, g as GLOB_XML, h as GLOB_SVG, i as GLOB_MARKDOWN, j as GLOB_GRAPHQL } from '../shared/eslint-config.CUi9znUC.mjs';
import 'eslint-flat-config-utils';
import 'eslint-config-flat-gitignore';
import 'pathe';
import 'node:process';
import '@nuxt/eslint-plugin';
import '@eslint/js';
import 'globals';
function mergePrettierOptions(options, overrides = {}) {
return {
...options,
...overrides,
plugins: [
...overrides.plugins || [],
...options.plugins || []
]
};
}
async function formatters(options = {}, stylistic) {
if (!options)
return [];
if (options === true) {
const isPrettierPluginXmlInScope = isPackageExists("@prettier/plugin-xml");
options = {
css: true,
graphql: true,
html: true,
// Markdown is disabled by default as many Nuxt projects use MDC with @nuxt/content,
// where Prettier doesn't fully understand.
markdown: false,
svg: isPrettierPluginXmlInScope,
xml: isPrettierPluginXmlInScope
};
}
await ensurePackages([
"eslint-plugin-format",
options.xml || options.svg ? "@prettier/plugin-xml" : void 0
]);
const {
indent,
quotes,
semi
} = {
indent: 2,
quotes: "single",
semi: false,
...stylistic
};
const prettierOptions = Object.assign(
{
endOfLine: "auto",
printWidth: 120,
semi,
singleQuote: quotes === "single",
tabWidth: typeof indent === "number" ? indent : 2,
trailingComma: "all",
useTabs: indent === "tab"
},
options.prettierOptions || {}
);
const prettierXmlOptions = {
xmlQuoteAttributes: "double",
xmlSelfClosingSpace: true,
xmlSortAttributesByKey: false,
xmlWhitespaceSensitivity: "ignore"
};
const dprintOptions = Object.assign(
{
indentWidth: typeof indent === "number" ? indent : 2,
quoteStyle: quotes === "single" ? "preferSingle" : "preferDouble",
useTabs: indent === "tab"
},
options.dprintOptions || {}
);
const pluginFormat = await interopDefault(import('eslint-plugin-format'));
const configs = [
{
name: "nuxt/formatter/setup",
plugins: {
format: pluginFormat
}
}
];
if (options.css) {
configs.push(
{
files: [GLOB_CSS, GLOB_POSTCSS],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/css",
rules: {
"format/prettier": [
"error",
mergePrettierOptions(prettierOptions, {
parser: "css"
})
]
}
},
{
files: [GLOB_SCSS],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/scss",
rules: {
"format/prettier": [
"error",
mergePrettierOptions(prettierOptions, {
parser: "scss"
})
]
}
},
{
files: [GLOB_LESS],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/less",
rules: {
"format/prettier": [
"error",
mergePrettierOptions(prettierOptions, {
parser: "less"
})
]
}
}
);
}
if (options.html) {
configs.push({
files: [GLOB_HTML],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/html",
rules: {
"format/prettier": [
"error",
mergePrettierOptions(prettierOptions, {
parser: "html"
})
]
}
});
}
if (options.xml) {
configs.push({
files: [GLOB_XML],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/xml",
rules: {
"format/prettier": [
"error",
mergePrettierOptions({ ...prettierXmlOptions, ...prettierOptions }, {
parser: "xml",
plugins: [
"@prettier/plugin-xml"
]
})
]
}
});
}
if (options.svg) {
configs.push({
files: [GLOB_SVG],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/svg",
rules: {
"format/prettier": [
"error",
mergePrettierOptions({ ...prettierXmlOptions, ...prettierOptions }, {
parser: "xml",
plugins: [
"@prettier/plugin-xml"
]
})
]
}
});
}
if (options.markdown) {
const formater = options.markdown === true ? "prettier" : options.markdown;
configs.push({
files: [GLOB_MARKDOWN],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/markdown",
rules: {
[`format/${formater}`]: [
"error",
formater === "prettier" ? mergePrettierOptions(prettierOptions, {
embeddedLanguageFormatting: "off",
parser: "markdown"
}) : {
...dprintOptions,
language: "markdown"
}
]
}
});
}
if (options.graphql) {
configs.push({
files: [GLOB_GRAPHQL],
languageOptions: {
parser: parserPlain
},
name: "nuxt/formatter/graphql",
rules: {
"format/prettier": [
"error",
mergePrettierOptions(prettierOptions, {
parser: "graphql"
})
]
}
});
}
return configs;
}
export { formatters };

View file

@ -0,0 +1,40 @@
import { r as resolveOptions } from '../shared/eslint-config.CePp8IWi.mjs';
import 'eslint-flat-config-utils';
import 'eslint-config-flat-gitignore';
import 'pathe';
import 'node:process';
import 'local-pkg';
import '@nuxt/eslint-plugin';
import '@eslint/js';
import 'globals';
async function imports(options) {
const resolved = resolveOptions(options);
if (resolved.features.import === false) {
return [];
}
const importOptions = resolved.features.import === true ? {} : resolved.features.import || {};
const plugin = importOptions.package === "eslint-plugin-import-lite" ? (await import('eslint-plugin-import-lite')).default : (await import('eslint-plugin-import-x')).default;
return [
{
name: "nuxt/import/rules",
plugins: {
import: plugin
},
rules: {
...importOptions.package === "eslint-plugin-import-lite" ? {
"import/consistent-type-specifier-style": ["error", "top-level"]
} : {},
"import/first": "error",
"import/no-duplicates": "error",
"import/no-mutable-exports": "error",
"import/no-named-default": "error",
...resolved.features.stylistic ? {
"import/newline-after-import": ["error", { count: 1 }]
} : {}
}
}
];
}
export { imports as default };

View file

@ -0,0 +1,47 @@
import jsdocPlugin from 'eslint-plugin-jsdoc';
import { G as GLOB_SRC, a as GLOB_VUE } from '../shared/eslint-config.CUi9znUC.mjs';
import { r as resolveOptions } from '../shared/eslint-config.CePp8IWi.mjs';
import 'eslint-flat-config-utils';
import 'eslint-config-flat-gitignore';
import 'pathe';
import 'node:process';
import 'local-pkg';
import '@nuxt/eslint-plugin';
import '@eslint/js';
import 'globals';
function jsdoc(options = {}) {
const resolved = resolveOptions(options);
return [
{
name: "nuxt/tooling/jsdoc",
files: [GLOB_SRC, GLOB_VUE],
plugins: {
jsdoc: jsdocPlugin
},
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",
...resolved.features.stylistic ? {
"jsdoc/check-alignment": "warn",
"jsdoc/multiline-blocks": "warn"
} : {}
}
}
];
}
export { jsdoc as default };

View file

@ -0,0 +1,14 @@
import { configs } from 'eslint-plugin-regexp';
import { G as GLOB_SRC, a as GLOB_VUE } from '../shared/eslint-config.CUi9znUC.mjs';
function regexp() {
return [
{
...configs["flat/recommended"],
name: "nuxt/tooling/regexp",
files: [GLOB_SRC, GLOB_VUE]
}
];
}
export { regexp as default };

View file

@ -0,0 +1,12 @@
import stylistic$1 from '@stylistic/eslint-plugin';
import { G as GLOB_SRC, a as GLOB_VUE } from '../shared/eslint-config.CUi9znUC.mjs';
const stylistic = (options) => {
return {
name: "nuxt/stylistic",
files: [GLOB_SRC, GLOB_VUE],
...stylistic$1.configs.customize(options)
};
};
export { stylistic as default };

View file

@ -0,0 +1,125 @@
import parserTs from '@typescript-eslint/parser';
export { default as parserTs } from '@typescript-eslint/parser';
import pluginTs from '@typescript-eslint/eslint-plugin';
export { default as pluginTs } from '@typescript-eslint/eslint-plugin';
import { r as resolveOptions } from '../shared/eslint-config.CePp8IWi.mjs';
import 'eslint-flat-config-utils';
import 'eslint-config-flat-gitignore';
import 'pathe';
import 'node:process';
import 'local-pkg';
import '@nuxt/eslint-plugin';
import '@eslint/js';
import 'globals';
const getRulesFromConfigs = (config) => {
const array = Array.isArray(config) ? config : [config];
const object = array.reduce((acc, item) => {
return { ...acc, ...item.rules };
}, {});
return object;
};
function typescript(options) {
const resolved = resolveOptions(options);
if (resolved.features.typescript === false) {
return [];
}
const tsOptions = resolved.features.typescript === true ? {} : resolved.features.typescript;
const strict = tsOptions.strict === false ? false : true;
const tsconfigPath = tsOptions.tsconfigPath || void 0;
return [
{
name: "nuxt/typescript/setup",
plugins: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
"@typescript-eslint": pluginTs
}
},
{
name: "nuxt/typescript/rules",
files: ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts", "**/*.vue"],
languageOptions: {
parser: parserTs,
parserOptions: {
extraFileExtensions: [".vue"],
sourceType: "module",
...tsconfigPath ? {
projectService: {
allowDefaultProject: ["./*.js"],
defaultProject: tsconfigPath
},
tsconfigRootDir: process.cwd()
} : {}
}
},
rules: {
...getRulesFromConfigs(pluginTs.configs["flat/recommended"]),
// Type-aware rules
...tsconfigPath ? getRulesFromConfigs(pluginTs.configs["flat/recommended-type-checked-only"]) : {},
// Strict rules
...strict ? tsconfigPath ? getRulesFromConfigs(pluginTs.configs["flat/strict-type-checked-only"]) : getRulesFromConfigs(pluginTs.configs["flat/strict"]) : {},
// Include typescript eslint rules in *.vue files
// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/configs/eslint-recommended.ts
"constructor-super": "off",
// ts(2335) & ts(2377)
"getter-return": "off",
// ts(2378)
"no-const-assign": "off",
// ts(2588)
"no-dupe-args": "off",
// ts(2300)
"no-dupe-class-members": "off",
// ts(2393) & ts(2300)
"no-dupe-keys": "off",
// ts(1117)
"no-func-assign": "off",
// ts(2539)
"no-import-assign": "off",
// ts(2539) & ts(2540)
"no-new-symbol": "off",
// ts(7009)
"no-obj-calls": "off",
// ts(2349)
"no-redeclare": "off",
// ts(2451)
"no-setter-return": "off",
// ts(2408)
"no-this-before-super": "off",
// ts(2376)
"no-undef": "off",
// ts(2304)
"no-unreachable": "off",
// ts(7027)
"no-unsafe-negation": "off",
// ts(2365) & ts(2360) & ts(2358)
"no-var": "error",
// ts transpiles let/const to var, so no need for vars any more
"prefer-const": "error",
// ts provides better types with const
"prefer-rest-params": "error",
// ts provides better types with rest args over arguments
"prefer-spread": "error",
// ts transpiles spread to apply, so no need for manual apply
"valid-typeof": "off",
// ts(2367)
"no-unused-vars": "off",
// ts takes care of this
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/consistent-type-imports": ["error", {
disallowTypeAnnotations: false,
prefer: "type-imports"
}],
"@typescript-eslint/no-unused-vars": ["error", {
args: "after-used",
argsIgnorePattern: "^_",
ignoreRestSiblings: true,
vars: "all",
varsIgnorePattern: "^_"
}],
"@typescript-eslint/no-import-type-side-effects": "error"
}
}
];
}
export { typescript as default };

View file

@ -0,0 +1,44 @@
import pluginUnicorn from 'eslint-plugin-unicorn';
import { G as GLOB_SRC, a as GLOB_VUE } from '../shared/eslint-config.CUi9znUC.mjs';
function unicorn() {
return [
{
name: "nuxt/tooling/unicorn",
files: [GLOB_SRC, GLOB_VUE],
plugins: {
unicorn: pluginUnicorn
},
rules: {
// Pass error message when throwing errors
"unicorn/error-message": "error",
// Uppercase regex escapes
"unicorn/escape-case": "error",
// Array.isArray instead of instanceof
"unicorn/no-instanceof-array": "error",
// Ban `new Array` as `Array` constructor's params are ambiguous
"unicorn/no-new-array": "error",
// Prevent deprecated `new Buffer()`
"unicorn/no-new-buffer": "error",
// Lowercase number formatting for octal, hex, binary (0x1'error' instead of 0X1'error')
"unicorn/number-literal-case": "error",
// textContent instead of innerText
"unicorn/prefer-dom-node-text-content": "error",
// includes over indexOf when checking for existence
"unicorn/prefer-includes": "error",
// Prefer using the node: protocol
"unicorn/prefer-node-protocol": "error",
// Prefer using number properties like `Number.isNaN` rather than `isNaN`
"unicorn/prefer-number-properties": "error",
// String methods startsWith/endsWith instead of more complicated stuff
"unicorn/prefer-string-starts-ends-with": "error",
// Enforce throwing type error when throwing error while checking typeof
"unicorn/prefer-type-error": "error",
// Use new when throwing error
"unicorn/throw-new-error": "error"
}
}
];
}
export { unicorn as default };

View file

@ -0,0 +1,156 @@
import * as parserVue from 'vue-eslint-parser';
import pluginVue from 'eslint-plugin-vue';
import processorVueBlocks from 'eslint-processor-vue-blocks';
import { mergeProcessors } from 'eslint-merge-processors';
import { r as resolveOptions, a as removeUndefined } from '../shared/eslint-config.CePp8IWi.mjs';
import 'eslint-flat-config-utils';
import 'eslint-config-flat-gitignore';
import 'pathe';
import 'node:process';
import 'local-pkg';
import '@nuxt/eslint-plugin';
import '@eslint/js';
import 'globals';
const INLINE_ELEMENTS = ["a", "abbr", "audio", "b", "bdi", "bdo", "canvas", "cite", "code", "data", "del", "dfn", "em", "i", "iframe", "ins", "kbd", "label", "map", "mark", "noscript", "object", "output", "picture", "q", "ruby", "s", "samp", "small", "span", "strong", "sub", "sup", "svg", "time", "u", "var", "video"];
async function vue(options) {
const resolved = resolveOptions(options);
const hasTs = resolved.features.typescript !== false;
const parser = hasTs ? await import('./typescript.mjs').then((mod) => mod.parserTs) : void 0;
const {
indent = 2,
commaDangle = "always-multiline"
} = typeof resolved.features.stylistic === "boolean" ? {} : resolved.features.stylistic;
const configs = [
{
name: "nuxt/vue/setup",
plugins: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
vue: pluginVue
},
languageOptions: {
parserOptions: {
ecmaVersion: "latest",
extraFileExtensions: [".vue"],
parser,
sourceType: "module",
ecmaFeatures: {
jsx: true
}
},
// This allows Vue plugin to work with auto imports
// https://github.com/vuejs/eslint-plugin-vue/pull/2422
globals: {
computed: "readonly",
defineEmits: "readonly",
defineExpose: "readonly",
defineProps: "readonly",
onMounted: "readonly",
onUnmounted: "readonly",
reactive: "readonly",
ref: "readonly",
shallowReactive: "readonly",
shallowRef: "readonly",
toRef: "readonly",
toRefs: "readonly",
watch: "readonly",
watchEffect: "readonly"
}
}
},
{
name: "nuxt/vue/rules",
files: [
"**/*.vue"
],
languageOptions: {
parser: parserVue
},
processor: options.features?.formatters ? mergeProcessors([
pluginVue.processors[".vue"],
processorVueBlocks({
blocks: {
styles: true
}
})
]) : pluginVue.processors[".vue"],
rules: {
...pluginVue.configs.base.rules,
...pluginVue.configs["flat/essential"].map((c) => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}),
...pluginVue.configs["flat/strongly-recommended"].map((c) => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}),
...pluginVue.configs["flat/recommended"].map((c) => c.rules).reduce((acc, c) => ({ ...acc, ...c }), {}),
// Deprecated in favor of 'vue/block-order'
"vue/component-tags-order": void 0,
"vue/block-order": "warn",
...resolved.features.stylistic ? {
"vue/array-bracket-spacing": ["error", "never"],
"vue/arrow-spacing": ["error", { after: true, before: true }],
"vue/block-spacing": ["error", "always"],
"vue/block-tag-newline": [
"error",
{
multiline: "always",
singleline: "always"
}
],
"vue/brace-style": ["error", "stroustrup", { allowSingleLine: true }],
"vue/html-indent": ["error", indent],
"vue/html-quotes": ["error", "double"],
"vue/comma-dangle": ["error", commaDangle],
"vue/comma-spacing": ["error", { after: true, before: false }],
"vue/comma-style": ["error", "last"],
"vue/html-comment-content-spacing": [
"error",
"always",
{ exceptions: ["-"] }
],
"vue/key-spacing": ["error", { afterColon: true, beforeColon: false }],
"vue/keyword-spacing": ["error", { after: true, before: true }],
"vue/object-curly-newline": "off",
"vue/object-curly-spacing": ["error", "always"],
"vue/object-property-newline": [
"error",
{ allowAllPropertiesOnSameLine: true }
],
"vue/one-component-per-file": "off",
"vue/operator-linebreak": ["error", "before"],
"vue/padding-line-between-blocks": ["error", "always"],
"vue/quote-props": ["error", "consistent-as-needed"],
"vue/require-default-prop": "off",
"vue/space-in-parens": ["error", "never"],
"vue/template-curly-spacing": "error",
"vue/multiline-html-element-content-newline": ["error", {
ignoreWhenEmpty: true,
ignores: ["pre", "textarea", "router-link", "RouterLink", "nuxt-link", "NuxtLink", "u-link", "ULink", ...INLINE_ELEMENTS],
allowEmptyLines: false
}],
"vue/singleline-html-element-content-newline": ["error", {
ignoreWhenNoAttributes: true,
ignoreWhenEmpty: true,
ignores: ["pre", "textarea", "router-link", "RouterLink", "nuxt-link", "NuxtLink", "u-link", "ULink", ...INLINE_ELEMENTS],
externalIgnores: []
}]
} : {
// Disable Vue's default stylistic rules when stylistic is not enabled
"vue/html-closing-bracket-newline": void 0,
"vue/html-closing-bracket-spacing": void 0,
"vue/html-indent": void 0,
"vue/html-quotes": void 0,
"vue/max-attributes-per-line": void 0,
"vue/multiline-html-element-content-newline": void 0,
"vue/mustache-interpolation-spacing": void 0,
"vue/no-multi-spaces": void 0,
"vue/no-spaces-around-equal-signs-in-attribute": void 0,
"vue/singleline-html-element-content-newline": void 0
}
}
}
];
for (const config of configs) {
if (config.rules)
config.rules = removeUndefined(config.rules);
}
return configs;
}
export { vue as default };

View file

@ -0,0 +1,3 @@
export { Awaitable, ImportPluginOptions, NuxtESLintConfigOptions, NuxtESLintConfigOptionsResolved, NuxtESLintFeaturesOptions, NuxtSpecificOptions, OptionsFormatters, ToolingOptions, default as createConfigForNuxt, defineFlatConfigs, resolveOptions } from './index.mjs';
import 'eslint-flat-config-utils';
import '@stylistic/eslint-plugin';

View file

@ -0,0 +1,3 @@
export { Awaitable, ImportPluginOptions, NuxtESLintConfigOptions, NuxtESLintConfigOptionsResolved, NuxtESLintFeaturesOptions, NuxtSpecificOptions, OptionsFormatters, ToolingOptions, default as createConfigForNuxt, defineFlatConfigs, resolveOptions } from './index.js';
import 'eslint-flat-config-utils';
import '@stylistic/eslint-plugin';

View file

@ -0,0 +1,9 @@
export { c as createConfigForNuxt, d as defineFlatConfigs, r as resolveOptions } from './shared/eslint-config.CePp8IWi.mjs';
import 'eslint-flat-config-utils';
import 'eslint-config-flat-gitignore';
import 'pathe';
import 'node:process';
import 'local-pkg';
import '@nuxt/eslint-plugin';
import '@eslint/js';
import 'globals';

View file

@ -0,0 +1,227 @@
import { ResolvableFlatConfig, FlatConfigComposer } from 'eslint-flat-config-utils';
import { StylisticCustomizeOptions } from '@stylistic/eslint-plugin';
interface ToolingOptions {
/**
* Enable RegExp rules
*
* @see https://github.com/ota-meshi/eslint-plugin-regexp
* @default true
*/
regexp?: boolean;
/**
* Enable Unicorn rules
*
* @see https://github.com/sindresorhus/eslint-plugin-unicorn
* @default true
*/
unicorn?: boolean;
/**
* Enable jsdoc rules
*
* @default true
*/
jsdoc?: boolean;
}
interface NuxtSpecificOptions {
/**
* Sort keys in nuxt.config to maintain a consistent order
*
* @default true when `features.stylistic` is enabled
*/
sortConfigKeys?: boolean;
}
interface NuxtESLintFeaturesOptions {
/**
* Setup basic JavaScript, TypeScript and Vue plugins and rules.
*
* You might want to disable it when you are using other ESLint config that handles the basic setup.
*
* @default true
*/
standalone?: boolean;
/**
* Enable rules for Nuxt module authors or library authors
*
* @experimental Changes might not follow semver
* @default false
*/
tooling?: boolean | ToolingOptions;
/**
* Enable the import plugin
*
* @default true
*/
import?: boolean | ImportPluginOptions;
/**
* Enable stylistic ESLint rules for formatting and code style check
*
* @see https://eslint.style/guide/config-presets
* @default false
*/
stylistic?: boolean | StylisticCustomizeOptions;
/**
* Enable formatters to handling formatting for different file types
*
* Requires `eslint-plugin-format` to be installed
*
* @default false
*/
formatters?: boolean | OptionsFormatters;
/**
* Options for Nuxt specific rules
*/
nuxt?: NuxtSpecificOptions;
/**
* Enable TypeScript support. Can also be an object to config the options.
*
* By default it enables automatic when `typescript` is installed in the project.
*/
typescript?: boolean | {
/**
* Enable strict rules
* @see https://typescript-eslint.io/users/configs#strict
* @default true
*/
strict?: boolean;
/**
* Path to the tsconfig file, when this is provide, type-aware rules will be enabled.
*/
tsconfigPath?: string;
};
}
interface ImportPluginOptions {
/**
* The import plugin to use
*
* @default 'eslint-plugin-import-x'
*/
package?: 'eslint-plugin-import-lite' | 'eslint-plugin-import-x';
}
interface NuxtESLintConfigOptions {
features?: NuxtESLintFeaturesOptions;
dirs?: {
/**
* Nuxt source directory
*/
src?: string[];
/**
* Root directory for nuxt project
*/
root?: string[];
/**
* Directory for pages
*/
pages?: string[];
/**
* Directory for layouts
*/
layouts?: string[];
/**
* Directory for components
*/
components?: string[];
/**
* Directory for components with prefix
* Ignore `vue/multi-word-component-names`
*/
componentsPrefixed?: string[];
/**
* Directory for composobles
*/
composables?: string[];
/**
* Directory for plugins
*/
plugins?: string[];
/**
* Directory for modules
*/
modules?: string[];
/**
* Directory for middleware
*/
middleware?: string[];
/**
* Directory for server
*/
servers?: string[];
};
}
interface OptionsFormatters {
/**
* Enable formatting support for CSS, Less, Sass, and SCSS.
*
* Currently only support Prettier.
*/
css?: 'prettier' | boolean;
/**
* Enable formatting support for HTML.
*
* Currently only support Prettier.
*/
html?: 'prettier' | boolean;
/**
* Enable formatting support for XML.
*
* Currently only support Prettier.
*/
xml?: 'prettier' | boolean;
/**
* Enable formatting support for SVG.
*
* Currently only support Prettier.
*/
svg?: 'prettier' | boolean;
/**
* Enable formatting support for Markdown.
*
* Support both Prettier and dprint.
*
* When set to `true`, it will use Prettier.
*/
markdown?: 'prettier' | 'dprint' | boolean;
/**
* Enable formatting support for GraphQL.
*/
graphql?: 'prettier' | boolean;
/**
* Custom options for Prettier.
*
* By default it's controlled by our own config.
*/
prettierOptions?: any;
/**
* Custom options for dprint.
*
* By default it's controlled by our own config.
*/
dprintOptions?: boolean;
}
type NotNill<T> = T extends null | undefined ? never : T;
interface NuxtESLintConfigOptionsResolved {
features: Required<NotNill<NuxtESLintFeaturesOptions>>;
dirs: Required<NotNill<NuxtESLintConfigOptions['dirs']>>;
}
type Awaitable<T> = T | Promise<T>;
declare function resolveOptions(config: NuxtESLintConfigOptions): NuxtESLintConfigOptionsResolved;
/**
* Provide type definitions for constructing ESLint flat config items.
*
* This function takes flat config item, or an array of them as rest arguments.
* It also automatically resolves the promise if the config item is a promise.
*/
declare function defineFlatConfigs(...configs: ResolvableFlatConfig[]): FlatConfigComposer;
/**
* Create an array of ESLint flat configs for Nuxt 3, based on the given options.
* Accepts appending user configs as rest arguments from the second argument.
*
* For Nuxt apps, it's recommended to use `@nuxt/eslint` module instead, which will generate the necessary configuration based on your project.
* @see https://eslint.nuxt.com/packages/module
*/
declare function createConfigForNuxt(options?: NuxtESLintConfigOptions, ...userConfigs: ResolvableFlatConfig[]): FlatConfigComposer;
export { createConfigForNuxt, createConfigForNuxt as default, defineFlatConfigs, resolveOptions };
export type { Awaitable, ImportPluginOptions, NuxtESLintConfigOptions, NuxtESLintConfigOptionsResolved, NuxtESLintFeaturesOptions, NuxtSpecificOptions, OptionsFormatters, ToolingOptions };

View file

@ -0,0 +1,227 @@
import { ResolvableFlatConfig, FlatConfigComposer } from 'eslint-flat-config-utils';
import { StylisticCustomizeOptions } from '@stylistic/eslint-plugin';
interface ToolingOptions {
/**
* Enable RegExp rules
*
* @see https://github.com/ota-meshi/eslint-plugin-regexp
* @default true
*/
regexp?: boolean;
/**
* Enable Unicorn rules
*
* @see https://github.com/sindresorhus/eslint-plugin-unicorn
* @default true
*/
unicorn?: boolean;
/**
* Enable jsdoc rules
*
* @default true
*/
jsdoc?: boolean;
}
interface NuxtSpecificOptions {
/**
* Sort keys in nuxt.config to maintain a consistent order
*
* @default true when `features.stylistic` is enabled
*/
sortConfigKeys?: boolean;
}
interface NuxtESLintFeaturesOptions {
/**
* Setup basic JavaScript, TypeScript and Vue plugins and rules.
*
* You might want to disable it when you are using other ESLint config that handles the basic setup.
*
* @default true
*/
standalone?: boolean;
/**
* Enable rules for Nuxt module authors or library authors
*
* @experimental Changes might not follow semver
* @default false
*/
tooling?: boolean | ToolingOptions;
/**
* Enable the import plugin
*
* @default true
*/
import?: boolean | ImportPluginOptions;
/**
* Enable stylistic ESLint rules for formatting and code style check
*
* @see https://eslint.style/guide/config-presets
* @default false
*/
stylistic?: boolean | StylisticCustomizeOptions;
/**
* Enable formatters to handling formatting for different file types
*
* Requires `eslint-plugin-format` to be installed
*
* @default false
*/
formatters?: boolean | OptionsFormatters;
/**
* Options for Nuxt specific rules
*/
nuxt?: NuxtSpecificOptions;
/**
* Enable TypeScript support. Can also be an object to config the options.
*
* By default it enables automatic when `typescript` is installed in the project.
*/
typescript?: boolean | {
/**
* Enable strict rules
* @see https://typescript-eslint.io/users/configs#strict
* @default true
*/
strict?: boolean;
/**
* Path to the tsconfig file, when this is provide, type-aware rules will be enabled.
*/
tsconfigPath?: string;
};
}
interface ImportPluginOptions {
/**
* The import plugin to use
*
* @default 'eslint-plugin-import-x'
*/
package?: 'eslint-plugin-import-lite' | 'eslint-plugin-import-x';
}
interface NuxtESLintConfigOptions {
features?: NuxtESLintFeaturesOptions;
dirs?: {
/**
* Nuxt source directory
*/
src?: string[];
/**
* Root directory for nuxt project
*/
root?: string[];
/**
* Directory for pages
*/
pages?: string[];
/**
* Directory for layouts
*/
layouts?: string[];
/**
* Directory for components
*/
components?: string[];
/**
* Directory for components with prefix
* Ignore `vue/multi-word-component-names`
*/
componentsPrefixed?: string[];
/**
* Directory for composobles
*/
composables?: string[];
/**
* Directory for plugins
*/
plugins?: string[];
/**
* Directory for modules
*/
modules?: string[];
/**
* Directory for middleware
*/
middleware?: string[];
/**
* Directory for server
*/
servers?: string[];
};
}
interface OptionsFormatters {
/**
* Enable formatting support for CSS, Less, Sass, and SCSS.
*
* Currently only support Prettier.
*/
css?: 'prettier' | boolean;
/**
* Enable formatting support for HTML.
*
* Currently only support Prettier.
*/
html?: 'prettier' | boolean;
/**
* Enable formatting support for XML.
*
* Currently only support Prettier.
*/
xml?: 'prettier' | boolean;
/**
* Enable formatting support for SVG.
*
* Currently only support Prettier.
*/
svg?: 'prettier' | boolean;
/**
* Enable formatting support for Markdown.
*
* Support both Prettier and dprint.
*
* When set to `true`, it will use Prettier.
*/
markdown?: 'prettier' | 'dprint' | boolean;
/**
* Enable formatting support for GraphQL.
*/
graphql?: 'prettier' | boolean;
/**
* Custom options for Prettier.
*
* By default it's controlled by our own config.
*/
prettierOptions?: any;
/**
* Custom options for dprint.
*
* By default it's controlled by our own config.
*/
dprintOptions?: boolean;
}
type NotNill<T> = T extends null | undefined ? never : T;
interface NuxtESLintConfigOptionsResolved {
features: Required<NotNill<NuxtESLintFeaturesOptions>>;
dirs: Required<NotNill<NuxtESLintConfigOptions['dirs']>>;
}
type Awaitable<T> = T | Promise<T>;
declare function resolveOptions(config: NuxtESLintConfigOptions): NuxtESLintConfigOptionsResolved;
/**
* Provide type definitions for constructing ESLint flat config items.
*
* This function takes flat config item, or an array of them as rest arguments.
* It also automatically resolves the promise if the config item is a promise.
*/
declare function defineFlatConfigs(...configs: ResolvableFlatConfig[]): FlatConfigComposer;
/**
* Create an array of ESLint flat configs for Nuxt 3, based on the given options.
* Accepts appending user configs as rest arguments from the second argument.
*
* For Nuxt apps, it's recommended to use `@nuxt/eslint` module instead, which will generate the necessary configuration based on your project.
* @see https://eslint.nuxt.com/packages/module
*/
declare function createConfigForNuxt(options?: NuxtESLintConfigOptions, ...userConfigs: ResolvableFlatConfig[]): FlatConfigComposer;
export { createConfigForNuxt, createConfigForNuxt as default, defineFlatConfigs, resolveOptions };
export type { Awaitable, ImportPluginOptions, NuxtESLintConfigOptions, NuxtESLintConfigOptionsResolved, NuxtESLintFeaturesOptions, NuxtSpecificOptions, OptionsFormatters, ToolingOptions };

View file

@ -0,0 +1,9 @@
import 'eslint-flat-config-utils';
import 'eslint-config-flat-gitignore';
export { c as createConfigForNuxt, c as default, d as defineFlatConfigs, r as resolveOptions } from './shared/eslint-config.CePp8IWi.mjs';
import 'pathe';
import 'node:process';
import 'local-pkg';
import '@nuxt/eslint-plugin';
import '@eslint/js';
import 'globals';

View file

@ -0,0 +1,13 @@
const GLOB_SRC = "**/*.?([cm])[jt]s?(x)";
const GLOB_CSS = "**/*.css";
const GLOB_POSTCSS = "**/*.{p,post}css";
const GLOB_LESS = "**/*.less";
const GLOB_SCSS = "**/*.scss";
const GLOB_MARKDOWN = "**/*.md";
const GLOB_VUE = "**/*.vue";
const GLOB_XML = "**/*.xml";
const GLOB_SVG = "**/*.svg";
const GLOB_HTML = "**/*.htm?(l)";
const GLOB_GRAPHQL = "**/*.{g,graph}ql";
export { GLOB_SRC as G, GLOB_VUE as a, GLOB_CSS as b, GLOB_POSTCSS as c, GLOB_SCSS as d, GLOB_LESS as e, GLOB_HTML as f, GLOB_XML as g, GLOB_SVG as h, GLOB_MARKDOWN as i, GLOB_GRAPHQL as j };

View file

@ -0,0 +1,286 @@
import { composer } from 'eslint-flat-config-utils';
import gitignore from 'eslint-config-flat-gitignore';
import { join } from 'pathe';
import process from 'node:process';
import { isPackageExists } from 'local-pkg';
import nuxtPlugin from '@nuxt/eslint-plugin';
import pluginESLint from '@eslint/js';
import globals from 'globals';
const GLOB_EXTS = "{js,ts,jsx,tsx,vue}";
const parserPlain = {
meta: {
name: "parser-plain"
},
parseForESLint: (code) => ({
ast: {
body: [],
comments: [],
loc: { end: code.length, start: 0 },
range: [0, code.length],
tokens: [],
type: "Program"
},
scopeManager: null,
services: { isPlain: true },
visitorKeys: {
Program: []
}
})
};
async function ensurePackages(packages) {
if (process.env.CI || !process.stdout.isTTY)
return;
const nonExistingPackages = packages.filter((i) => i && !isPackageExists(i));
if (nonExistingPackages.length === 0)
return;
const p = await import('@clack/prompts');
const result = await p.confirm({
message: `${nonExistingPackages.length === 1 ? "Package is" : "Packages are"} required for this config: ${nonExistingPackages.join(", ")}. Do you want to install them?`
});
if (result)
await import('@antfu/install-pkg').then((i) => i.installPackage(nonExistingPackages, { dev: true }));
}
async function interopDefault(m) {
const resolved = await m;
return resolved.default || resolved;
}
function removeUndefined(obj) {
return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== void 0));
}
function resolveOptions(config) {
if ("__resolved" in config) {
return config;
}
const dirs = {
...config.dirs
};
dirs.root ||= [".", "./app"];
dirs.src ||= dirs.root;
dirs.pages ||= dirs.src.map((src) => `${src}/pages`);
dirs.layouts ||= dirs.src.map((src) => `${src}/layouts`);
dirs.components ||= dirs.src.map((src) => `${src}/components`);
dirs.composables ||= dirs.src.map((src) => `${src}/composables`);
dirs.plugins ||= dirs.src.map((src) => `${src}/plugins`);
dirs.modules ||= dirs.src.map((src) => `${src}/modules`);
dirs.middleware ||= dirs.src.map((src) => `${src}/middleware`);
dirs.servers ||= dirs.src.map((src) => `${src}/servers`);
dirs.componentsPrefixed ||= [];
const resolved = {
features: {
standalone: true,
stylistic: false,
typescript: isPackageExists("typescript"),
tooling: false,
formatters: false,
nuxt: {},
import: {},
...config.features
},
dirs
};
Object.defineProperty(resolved, "__resolved", { value: true, enumerable: false });
return resolved;
}
function disables(options) {
const resolved = resolveOptions(options);
const dirs = resolved.dirs;
const nestedGlobPattern = `**/*.${GLOB_EXTS}`;
const fileRoutes = [.../* @__PURE__ */ new Set([
// These files must have one-word names as they have a special meaning in Nuxt.
...dirs.src.flatMap((layersDir) => [
join(layersDir, `app.${GLOB_EXTS}`),
join(layersDir, `error.${GLOB_EXTS}`)
]) || [],
// Layouts and pages are not used directly by users so they can have one-word names.
...dirs.layouts.map((layoutsDir) => join(layoutsDir, nestedGlobPattern)) || [],
...dirs.pages.map((pagesDir) => join(pagesDir, nestedGlobPattern)) || [],
// These files should have multiple words in their names as they are within subdirectories.
...dirs.components.map((componentsDir) => join(componentsDir, "*", nestedGlobPattern)) || [],
// Prefixed components can have one-word names in file
...dirs.componentsPrefixed.map((componentsDir) => join(componentsDir, nestedGlobPattern)) || []
])].sort();
const configs = [];
if (fileRoutes.length) {
configs.push({
name: "nuxt/disables/routes",
files: fileRoutes,
rules: {
"vue/multi-word-component-names": "off"
}
});
}
return configs;
}
function nuxt(options) {
const resolved = resolveOptions(options);
const dirs = resolved.dirs;
const fileSingleRoot = [
...dirs.layouts?.map((layoutsDir) => join(layoutsDir, `**/*.${GLOB_EXTS}`)) || [],
...dirs.pages?.map((pagesDir) => join(pagesDir, `**/*.${GLOB_EXTS}`)) || [],
...dirs.components?.map((componentsDir) => join(componentsDir, `**/*.server.${GLOB_EXTS}`)) || []
].sort();
const {
sortConfigKeys = !!options.features?.stylistic
} = options.features?.nuxt || {};
const configs = [];
configs.push({
name: "nuxt/setup",
plugins: {
nuxt: nuxtPlugin
},
languageOptions: {
globals: {
// Nuxt's runtime globals
$fetch: "readonly"
}
}
});
if (fileSingleRoot.length)
configs.push({
name: "nuxt/vue/single-root",
files: fileSingleRoot,
rules: {
"vue/no-multiple-template-root": "error"
}
});
configs.push({
name: "nuxt/rules",
rules: {
"nuxt/prefer-import-meta": "error"
}
});
configs.push({
name: "nuxt/nuxt-config",
files: [
"**/.config/nuxt.?([cm])[jt]s?(x)",
"**/nuxt.config.?([cm])[jt]s?(x)"
],
rules: {
"nuxt/no-nuxt-config-test-key": "error"
}
});
if (sortConfigKeys) {
configs.push({
name: "nuxt/sort-config",
files: [
"**/.config/nuxt.?([cm])[jt]s?(x)",
"**/nuxt.config.?([cm])[jt]s?(x)"
],
rules: {
"nuxt/nuxt-config-keys-order": "error"
}
});
}
return configs;
}
function ignores() {
return [
{
ignores: [
"**/dist",
"**/node_modules",
"**/.nuxt",
"**/.output",
"**/.vercel",
"**/.netlify",
"**/public"
]
}
];
}
function javascript() {
return [
{
...pluginESLint.configs.recommended,
name: "nuxt/javascript",
languageOptions: {
ecmaVersion: 2022,
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 2022,
sourceType: "module"
},
sourceType: "module",
globals: {
...globals.browser,
...globals.es2021,
...globals.node,
document: "readonly",
navigator: "readonly",
window: "readonly",
// This is technically not a global function, but it's a common practice in nuxt.config.ts,
// we include it here to avoid false positives.
defineNuxtConfig: "readonly"
}
},
linterOptions: {
reportUnusedDisableDirectives: true
}
}
];
}
function defineFlatConfigs(...configs) {
return composer(...configs);
}
function createConfigForNuxt(options = {}, ...userConfigs) {
const c = composer();
const resolved = resolveOptions(options);
if (resolved.features.standalone !== false) {
c.append(
gitignore({ strict: false }),
ignores(),
javascript(),
// Make these imports async, as they are optional and imports plugins
resolved.features.typescript !== false ? import('../chunks/typescript.mjs').then((m) => m.default(resolved)) : void 0,
import('../chunks/vue.mjs').then((m) => m.default(resolved)),
import('../chunks/import.mjs').then((m) => m.default(resolved))
);
}
c.append(
nuxt(resolved)
);
if (resolved.features.tooling) {
const toolingOptions = typeof resolved.features.tooling === "boolean" ? {} : resolved.features.tooling;
c.append(
toolingOptions.jsdoc !== false && import('../chunks/jsdoc.mjs').then((m) => m.default(resolved)),
toolingOptions.unicorn !== false && import('../chunks/unicorn.mjs').then((m) => m.default()),
toolingOptions.regexp !== false && import('../chunks/regexp.mjs').then((m) => m.default())
);
}
const stylisticOptions = typeof resolved.features.stylistic === "boolean" ? {} : resolved.features.stylistic;
if (resolved.features.stylistic) {
c.append(
import('../chunks/stylistic.mjs').then((m) => m.default(stylisticOptions))
);
}
if (resolved.features.formatters) {
c.append(
import('../chunks/formatters.mjs').then((m) => m.formatters(resolved.features.formatters, stylisticOptions))
);
}
c.append(
disables(resolved)
);
if (userConfigs.length > 0) {
c.append(...userConfigs);
}
c.setPluginConflictsError().setPluginConflictsError("import", [
'Different instances of plugin "{{pluginName}}" found in multiple configs:',
"{{configNames}}.",
"You might forget to set `standalone: false`.",
"Please refer to https://eslint.nuxt.com/packages/module#custom-config-presets.",
""
].join("\n"));
return c;
}
export { removeUndefined as a, createConfigForNuxt as c, defineFlatConfigs as d, ensurePackages as e, interopDefault as i, parserPlain as p, resolveOptions as r };