Some checks failed
📦 Build / build (push) Has been cancelled
🧪 CI Test / test shard (1/4) (push) Has been cancelled
🧪 CI Test / test shard (2/4) (push) Has been cancelled
🧪 CI Test / test shard (3/4) (push) Has been cancelled
🧪 CI Test / test shard (4/4) (push) Has been cancelled
🧪 CI Test / test (push) Has been cancelled
🧪 CI Test / eslint (push) Has been cancelled
🧪 CI Test / typecheck (push) Has been cancelled
🔫 Sync to Pro / dispatch-sync (push) Has been cancelled
🔮 Sync Mirror / sync (push) Has been cancelled
297 lines
9.1 KiB
TypeScript
297 lines
9.1 KiB
TypeScript
import type { ESLint, Linter } from 'eslint';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { fixupPluginRules } from '@eslint/compat';
|
|
import typescriptParser from '@typescript-eslint/parser';
|
|
import eslintPluginBetterTailwindcss from 'eslint-plugin-better-tailwindcss';
|
|
import header from 'eslint-plugin-header';
|
|
import barrel from 'eslint-plugin-no-barrel-import';
|
|
import penetrating from 'eslint-plugin-no-penetrating-import';
|
|
import noExternalImportsInFacade from './plugins/no-external-imports-in-facade';
|
|
import noFacadeImportsOutsideFacade from './plugins/no-facade-imports-outside-facade';
|
|
import noMixedTypeSpecifiersInIndex from './plugins/no-mixed-type-specifiers-in-index';
|
|
import noSelfPackageImports from './plugins/no-self-package-imports';
|
|
|
|
const univerPlugin = {
|
|
rules: {
|
|
'no-external-imports-in-facade': noExternalImportsInFacade,
|
|
'no-self-package-imports': noSelfPackageImports,
|
|
'no-facade-imports-outside-facade': noFacadeImportsOutsideFacade,
|
|
'no-mixed-type-specifiers-in-index': noMixedTypeSpecifiersInIndex,
|
|
},
|
|
} satisfies ESLint.Plugin;
|
|
|
|
/**
|
|
* TypeScript preset configuration for ESLint.
|
|
* Applies TypeScript-specific rules and custom Univer rules.
|
|
*
|
|
* @returns ESLint configuration object for TypeScript files
|
|
*/
|
|
export const typescriptPreset = (): Linter.Config => {
|
|
return {
|
|
files: ['**/*.{ts,tsx,mts,cts}'],
|
|
rules: {
|
|
'ts/naming-convention': [
|
|
'warn',
|
|
// Interfaces' names should start with a capital 'I'.
|
|
{
|
|
selector: 'interface',
|
|
format: ['PascalCase'],
|
|
custom: {
|
|
regex: '^I[A-Z0-9]',
|
|
match: true,
|
|
},
|
|
},
|
|
// Private fields of a class should start with an underscore '_'.
|
|
{
|
|
selector: ['classMethod', 'classProperty'],
|
|
modifiers: ['private'],
|
|
format: ['camelCase'],
|
|
leadingUnderscore: 'require',
|
|
},
|
|
],
|
|
// 'ts/consistent-type-exports': 'warn',
|
|
},
|
|
languageOptions: {
|
|
parser: typescriptParser,
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Index entry preset configuration for ESLint.
|
|
* Keeps type-only imports and exports separate from value imports and exports.
|
|
*
|
|
* @returns ESLint configuration object for package entry files
|
|
*/
|
|
export const indexEntryPreset = (): Linter.Config => {
|
|
return {
|
|
files: ['**/src/index.ts'],
|
|
rules: {
|
|
'univer/no-mixed-type-specifiers-in-index': 'error',
|
|
},
|
|
plugins: {
|
|
univer: univerPlugin,
|
|
},
|
|
languageOptions: {
|
|
parser: typescriptParser,
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Univer source code preset configuration.
|
|
* Enforces package structure rules for source files.
|
|
*
|
|
* @returns ESLint configuration object for Univer source files
|
|
*/
|
|
export const univerSourcePreset = (options: {
|
|
noFacadeImportsOutsideFacade?: {
|
|
ignore?: string[];
|
|
};
|
|
} = {}): Linter.Config => {
|
|
return {
|
|
files: ['**/*.ts', '**/*.tsx'],
|
|
ignores: [
|
|
'**/__tests__/**/*',
|
|
'**/*.spec.ts',
|
|
'**/*.test.ts',
|
|
],
|
|
rules: {
|
|
'univer/no-self-package-imports': 'error',
|
|
'univer/no-facade-imports-outside-facade': ['error', {
|
|
ignore: options.noFacadeImportsOutsideFacade?.ignore ?? [],
|
|
}],
|
|
},
|
|
plugins: {
|
|
univer: univerPlugin,
|
|
},
|
|
languageOptions: {
|
|
parser: typescriptParser,
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Facade preset configuration for ESLint.
|
|
* Enforces strict typing and import rules for facade files.
|
|
*
|
|
* @returns ESLint configuration object for facade files
|
|
*/
|
|
export const facadePreset = (): Linter.Config => {
|
|
return {
|
|
files: ['**/src/facade/**/*.ts'],
|
|
ignores: [
|
|
'**/__tests__/**/*',
|
|
'**/*.spec.ts',
|
|
'**/*.test.ts',
|
|
],
|
|
rules: {
|
|
'ts/explicit-function-return-type': 'error',
|
|
'univer/no-external-imports-in-facade': 'error',
|
|
},
|
|
plugins: {
|
|
univer: univerPlugin,
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Tailwind CSS preset configuration for ESLint.
|
|
* Enforces Tailwind CSS class usage and formatting rules.
|
|
*
|
|
* @returns ESLint configuration object for files using Tailwind CSS
|
|
*/
|
|
export const tailwindcssPreset = (): Linter.Config => {
|
|
const isWindows = os.platform() === 'win32';
|
|
const lineBreakStyle = isWindows ? 'windows' : 'unix';
|
|
|
|
return {
|
|
files: ['**/*.tsx'],
|
|
languageOptions: {
|
|
parserOptions: {
|
|
ecmaFeatures: {
|
|
jsx: true,
|
|
},
|
|
},
|
|
},
|
|
plugins: {
|
|
'better-tailwindcss': eslintPluginBetterTailwindcss,
|
|
},
|
|
settings: {
|
|
'better-tailwindcss': {
|
|
tailwindConfig: path.resolve(__dirname, '../tailwind/tailwind.config.ts'),
|
|
},
|
|
},
|
|
rules: {
|
|
// enable all recommended rules to error
|
|
...eslintPluginBetterTailwindcss.configs['recommended-error'].rules,
|
|
'better-tailwindcss/enforce-consistent-line-wrapping': ['error', {
|
|
printWidth: 120,
|
|
group: 'newLine',
|
|
lineBreakStyle,
|
|
}],
|
|
'better-tailwindcss/no-unknown-classes': 'off',
|
|
'better-tailwindcss/no-conflicting-classes': 'off',
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Test/spec files preset configuration for ESLint.
|
|
* Relaxed rules for test files to allow more flexible testing patterns.
|
|
*
|
|
* @returns ESLint configuration object for test files
|
|
*/
|
|
export const specPreset = (): Linter.Config => {
|
|
return {
|
|
files: [
|
|
'**/*.spec.ts',
|
|
'**/__tests__/**/*.ts',
|
|
],
|
|
rules: {
|
|
'ts/explicit-function-return-type': 'off',
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Penetrating import preset configuration for ESLint.
|
|
* Prevents direct imports from internal package directories.
|
|
*
|
|
* @returns ESLint configuration object for preventing penetrating imports
|
|
*/
|
|
export const penetratingPreset = (): Linter.Config => {
|
|
return {
|
|
// Not penetrating for source files
|
|
files: ['**/*.ts', '**/*.tsx'],
|
|
plugins: {
|
|
penetrating: fixupPluginRules(penetrating),
|
|
},
|
|
ignores: [
|
|
'**/__tests__/**/*',
|
|
'**/__testing__/**/*',
|
|
'examples/**/*',
|
|
],
|
|
rules: {
|
|
'penetrating/no-penetrating-import': 2,
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* No barrel import preset configuration for ESLint.
|
|
* Prevents barrel imports and enforces code complexity limits.
|
|
*
|
|
* @returns ESLint configuration object for preventing barrel imports
|
|
*/
|
|
export const noBarrelImportPreset = (): Linter.Config => {
|
|
return {
|
|
files: ['**/*.ts', '**/*.tsx'],
|
|
ignores: [
|
|
'packages/engine-render/src/components/docs/**/*.ts',
|
|
'**/*.tsx',
|
|
'**/*.d.ts',
|
|
'**/tsdown.config.ts',
|
|
'**/*.spec.ts',
|
|
'**/*.spec.tsx',
|
|
'**/*.test.ts',
|
|
'**/*.test.tsx',
|
|
], // do not check test files
|
|
plugins: {
|
|
barrel: fixupPluginRules(barrel),
|
|
},
|
|
rules: {
|
|
'barrel/no-barrel-import': 2,
|
|
complexity: ['warn', { max: 20 }],
|
|
'max-lines-per-function': ['warn', 80],
|
|
},
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Header preset configuration for ESLint.
|
|
* Enforces Apache License 2.0 header in package and preset source files.
|
|
*
|
|
* @returns ESLint configuration object for enforcing file headers
|
|
*/
|
|
export const headerPreset = (): Linter.Config => {
|
|
header.rules.header.meta.schema = false;
|
|
|
|
return {
|
|
files: ['{packages,presets}/**/*.{ts,tsx}'],
|
|
ignores: [
|
|
'**/*.d.ts',
|
|
'**/vitest.config.ts',
|
|
'**/vitest.workspace.ts',
|
|
],
|
|
plugins: {
|
|
header: fixupPluginRules(header),
|
|
},
|
|
rules: {
|
|
'header/header': [
|
|
2,
|
|
'block',
|
|
[
|
|
'*',
|
|
' * Copyright 2023-present DreamNum Co., Ltd.',
|
|
' *',
|
|
' * Licensed under the Apache License, Version 2.0 (the "License");',
|
|
' * you may not use this file except in compliance with the License.',
|
|
' * You may obtain a copy of the License at',
|
|
' *',
|
|
' * http://www.apache.org/licenses/LICENSE-2.0',
|
|
' *',
|
|
' * Unless required by applicable law or agreed to in writing, software',
|
|
' * distributed under the License is distributed on an "AS IS" BASIS,',
|
|
' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
|
|
' * See the License for the specific language governing permissions and',
|
|
' * limitations under the License.',
|
|
' ',
|
|
],
|
|
2,
|
|
],
|
|
},
|
|
};
|
|
};
|