Merge branch 'main' into feature/fsd-structure
This commit is contained in:
@@ -63,6 +63,7 @@ export function buildPlugins({
|
|||||||
plugins.push(
|
plugins.push(
|
||||||
new BundleAnalyzerPlugin({
|
new BundleAnalyzerPlugin({
|
||||||
openAnalyzer: false,
|
openAnalyzer: false,
|
||||||
|
analyzerMode: 'static',
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
plugins.push(new ReactRefreshWebpackPlugin({ overlay: false }))
|
plugins.push(new ReactRefreshWebpackPlugin({ overlay: false }))
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ export function buildResolvers(options: BuildOptions): webpack.ResolveOptions {
|
|||||||
preferAbsolute: true,
|
preferAbsolute: true,
|
||||||
modules: [options.paths.src, 'node_modules'],
|
modules: [options.paths.src, 'node_modules'],
|
||||||
mainFiles: ['index'],
|
mainFiles: ['index'],
|
||||||
alias: {},
|
alias: {
|
||||||
|
'@': options.paths.src,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'
|
|||||||
*/
|
*/
|
||||||
export const buildCssLoader = (isDev: boolean) => {
|
export const buildCssLoader = (isDev: boolean) => {
|
||||||
const cssLoader = {
|
const cssLoader = {
|
||||||
test: /\.s[ac]ss$/i,
|
test: /\.(s[ac]ss|css)$/i,
|
||||||
use: [
|
use: [
|
||||||
// Создает <style> теги из JS строк (dev) или извлекает в файлы (prod)
|
// Создает <style> теги из JS строк (dev) или извлекает в файлы (prod)
|
||||||
isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
|
isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
|
||||||
@@ -28,6 +28,7 @@ export const buildCssLoader = (isDev: boolean) => {
|
|||||||
options: {
|
options: {
|
||||||
modules: {
|
modules: {
|
||||||
auto: /\.module\..*$/,
|
auto: /\.module\..*$/,
|
||||||
|
namedExport: false,
|
||||||
localIdentName: isDev
|
localIdentName: isDev
|
||||||
? '[path][name]__[local]--[hash:base64:5]'
|
? '[path][name]__[local]--[hash:base64:5]'
|
||||||
: '[hash:base64:8]',
|
: '[hash:base64:8]',
|
||||||
|
|||||||
@@ -41,213 +41,225 @@ import globals from 'globals'
|
|||||||
import tseslint from 'typescript-eslint'
|
import tseslint from 'typescript-eslint'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
/**
|
/**
|
||||||
* Базовые конфигурации
|
* Базовые конфигурации
|
||||||
*/
|
*/
|
||||||
js.configs.recommended,
|
js.configs.recommended,
|
||||||
...tseslint.configs.recommended,
|
...tseslint.configs.recommended,
|
||||||
prettierConfig,
|
prettierConfig,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Глобальные исключения (не проверяются линтером)
|
* Глобальные исключения (не проверяются линтером)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ignores: [
|
ignores: [
|
||||||
'dist/**',
|
'dist/**',
|
||||||
'node_modules/**',
|
'node_modules/**',
|
||||||
'.fttemplates/**',
|
'.fttemplates/**',
|
||||||
'*.config.js',
|
'*.config.js',
|
||||||
'*.config.mjs',
|
'*.config.mjs',
|
||||||
'*.config.ts',
|
'*.config.ts',
|
||||||
],
|
],
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Основная конфигурация для всех файлов
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
|
|
||||||
plugins: {
|
|
||||||
react: reactPlugin,
|
|
||||||
'react-hooks': reactHooksPlugin,
|
|
||||||
'jsx-a11y': jsxA11yPlugin,
|
|
||||||
import: importPlugin,
|
|
||||||
jest: jestPlugin,
|
|
||||||
prettier: prettierPlugin,
|
|
||||||
},
|
},
|
||||||
languageOptions: {
|
|
||||||
ecmaVersion: 'latest',
|
/**
|
||||||
sourceType: 'module',
|
* Основная конфигурация для всех файлов
|
||||||
parser: tseslint.parser,
|
*/
|
||||||
parserOptions: {
|
{
|
||||||
ecmaFeatures: {
|
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
|
||||||
jsx: true,
|
plugins: {
|
||||||
|
react: reactPlugin,
|
||||||
|
'react-hooks': reactHooksPlugin,
|
||||||
|
'jsx-a11y': jsxA11yPlugin,
|
||||||
|
import: importPlugin,
|
||||||
|
jest: jestPlugin,
|
||||||
|
prettier: prettierPlugin,
|
||||||
},
|
},
|
||||||
},
|
languageOptions: {
|
||||||
globals: {
|
ecmaVersion: 'latest',
|
||||||
...globals.browser,
|
sourceType: 'module',
|
||||||
...globals.es2021,
|
parser: tseslint.parser,
|
||||||
...globals.jest,
|
parserOptions: {
|
||||||
__IS_DEV__: 'readonly',
|
ecmaFeatures: {
|
||||||
__API__: 'readonly',
|
jsx: true,
|
||||||
__PROJECT__: 'readonly',
|
},
|
||||||
},
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
react: {
|
|
||||||
version: 'detect',
|
|
||||||
},
|
|
||||||
'import/resolver': {
|
|
||||||
typescript: true,
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
/**
|
|
||||||
* Правила для импортов
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** Упорядочивание импортов по группам с алфавитной сортировкой */
|
|
||||||
'import/order': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
groups: [
|
|
||||||
['external', 'builtin'],
|
|
||||||
'internal',
|
|
||||||
['sibling', 'parent'],
|
|
||||||
'index',
|
|
||||||
],
|
|
||||||
pathGroups: [
|
|
||||||
{
|
|
||||||
pattern: '@react',
|
|
||||||
group: 'external',
|
|
||||||
position: 'before',
|
|
||||||
},
|
},
|
||||||
{
|
globals: {
|
||||||
pattern: '@src/**',
|
...globals.browser,
|
||||||
group: 'internal',
|
...globals.es2021,
|
||||||
|
...globals.jest,
|
||||||
|
__IS_DEV__: 'readonly',
|
||||||
|
__API__: 'readonly',
|
||||||
|
__PROJECT__: 'readonly',
|
||||||
},
|
},
|
||||||
],
|
|
||||||
pathGroupsExcludedImportTypes: ['internal', 'react'],
|
|
||||||
'newlines-between': 'always',
|
|
||||||
alphabetize: {
|
|
||||||
order: 'asc',
|
|
||||||
caseInsensitive: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
settings: {
|
||||||
'import/no-unresolved': 'off',
|
react: {
|
||||||
'import/no-extraneous-dependencies': 'off',
|
version: 'detect',
|
||||||
'import/extensions': 'off',
|
},
|
||||||
'import/prefer-default-export': 'off',
|
'import/resolver': {
|
||||||
'import/no-import-module-exports': 'off',
|
typescript: true,
|
||||||
|
node: true,
|
||||||
/**
|
},
|
||||||
* Правила для React
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** Определение компонентов через стрелочные функции или function declaration */
|
|
||||||
'react/function-component-definition': [
|
|
||||||
2,
|
|
||||||
{
|
|
||||||
namedComponents: ['arrow-function', 'function-declaration'],
|
|
||||||
unnamedComponents: ['arrow-function', 'function-expression'],
|
|
||||||
},
|
},
|
||||||
],
|
rules: {
|
||||||
'react/jsx-filename-extension': [
|
/**
|
||||||
2,
|
* Правила для импортов
|
||||||
{ extensions: ['.tsx', '.jsx', '.js'] },
|
*/
|
||||||
],
|
|
||||||
'react/require-default-props': 'off',
|
|
||||||
'react/jsx-props-no-spreading': 'warn',
|
|
||||||
'react/display-name': 'off',
|
|
||||||
'react/jsx-no-useless-fragment': [2, { allowExpressions: true }],
|
|
||||||
/** Не нужен с новым JSX transform */
|
|
||||||
'react/react-in-jsx-scope': 'off',
|
|
||||||
|
|
||||||
/**
|
/** Упорядочивание импортов по группам с алфавитной сортировкой */
|
||||||
* Правила для React Hooks
|
'import/order': [
|
||||||
*/
|
'error',
|
||||||
|
{
|
||||||
|
groups: [
|
||||||
|
['external', 'builtin'],
|
||||||
|
'internal',
|
||||||
|
['sibling', 'parent'],
|
||||||
|
'index',
|
||||||
|
'type',
|
||||||
|
],
|
||||||
|
pathGroups: [
|
||||||
|
{
|
||||||
|
pattern: '@react',
|
||||||
|
group: 'external',
|
||||||
|
position: 'before',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: '@/**',
|
||||||
|
group: 'internal',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
pathGroupsExcludedImportTypes: ['type'],
|
||||||
|
'newlines-between': 'always',
|
||||||
|
distinctGroup: false,
|
||||||
|
alphabetize: {
|
||||||
|
order: 'asc',
|
||||||
|
caseInsensitive: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/no-unresolved': 'off',
|
||||||
|
'import/no-extraneous-dependencies': 'off',
|
||||||
|
'import/extensions': 'off',
|
||||||
|
'import/prefer-default-export': 'off',
|
||||||
|
'import/no-import-module-exports': 'off',
|
||||||
|
|
||||||
/** Проверка правил хуков */
|
/**
|
||||||
'react-hooks/rules-of-hooks': 'error',
|
* Правила для React
|
||||||
/** Проверка зависимостей эффектов */
|
*/
|
||||||
'react-hooks/exhaustive-deps': 'error',
|
|
||||||
|
|
||||||
/**
|
/** Определение компонентов через стрелочные функции или function declaration */
|
||||||
* Правила доступности (A11y)
|
'react/function-component-definition': [
|
||||||
*/
|
2,
|
||||||
|
{
|
||||||
|
namedComponents: ['arrow-function', 'function-declaration'],
|
||||||
|
unnamedComponents: ['arrow-function', 'function-expression'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react/jsx-filename-extension': [
|
||||||
|
2,
|
||||||
|
{ extensions: ['.tsx', '.jsx', '.js'] },
|
||||||
|
],
|
||||||
|
'react/require-default-props': 'off',
|
||||||
|
'react/jsx-props-no-spreading': 'warn',
|
||||||
|
'react/display-name': 'off',
|
||||||
|
'react/jsx-no-useless-fragment': [2, { allowExpressions: true }],
|
||||||
|
/** Не нужен с новым JSX transform */
|
||||||
|
'react/react-in-jsx-scope': 'off',
|
||||||
|
|
||||||
'jsx-a11y/click-events-have-key-events': 'warn',
|
/**
|
||||||
'jsx-a11y/no-static-element-interactions': 'warn',
|
* Правила для React Hooks
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/** Проверка правил хуков */
|
||||||
* Правила для TypeScript
|
'react-hooks/rules-of-hooks': 'error',
|
||||||
*/
|
/** Проверка зависимостей эффектов */
|
||||||
|
'react-hooks/exhaustive-deps': 'error',
|
||||||
|
|
||||||
'@typescript-eslint/no-shadow': 'warn',
|
/**
|
||||||
'@typescript-eslint/no-unused-vars': 'warn',
|
* Правила доступности (A11y)
|
||||||
'@typescript-eslint/no-var-requires': 'warn',
|
*/
|
||||||
'@typescript-eslint/no-use-before-define': ['error', { enums: false }],
|
|
||||||
'@typescript-eslint/naming-convention': 'warn',
|
|
||||||
'@typescript-eslint/ban-ts-comment': 'warn',
|
|
||||||
|
|
||||||
/**
|
'jsx-a11y/click-events-have-key-events': 'warn',
|
||||||
* Общие правила JavaScript/TypeScript
|
'jsx-a11y/no-static-element-interactions': 'warn',
|
||||||
*/
|
|
||||||
|
|
||||||
/** Точки с запятой контролируются Prettier */
|
/**
|
||||||
semi: 'off',
|
* Правила для TypeScript
|
||||||
'jsx-quotes': ['error', 'prefer-single'],
|
*/
|
||||||
'no-shadow': 'off',
|
|
||||||
'no-unused-vars': 'off',
|
'@typescript-eslint/no-shadow': 'warn',
|
||||||
'no-underscore-dangle': 'off',
|
'@typescript-eslint/no-unused-vars': 'warn',
|
||||||
'no-use-before-define': 'off',
|
'@typescript-eslint/no-var-requires': 'warn',
|
||||||
'no-param-reassign': ['warn', { props: false }],
|
'@typescript-eslint/no-use-before-define': ['error', { enums: false }],
|
||||||
'max-len': [
|
'@typescript-eslint/naming-convention': [
|
||||||
2,
|
'warn',
|
||||||
{
|
{
|
||||||
ignoreComments: true,
|
selector: 'function',
|
||||||
ignoreUrls: true,
|
format: ['camelCase', 'PascalCase'],
|
||||||
code: 140,
|
},
|
||||||
ignorePattern: '^(import\\s.+\\sfrom\\s.+|\\} from)',
|
{
|
||||||
|
selector: 'variable',
|
||||||
|
format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/ban-ts-comment': 'warn',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Общие правила JavaScript/TypeScript
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Точки с запятой контролируются Prettier */
|
||||||
|
semi: 'off',
|
||||||
|
'jsx-quotes': ['error', 'prefer-single'],
|
||||||
|
'no-shadow': 'off',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'no-underscore-dangle': 'off',
|
||||||
|
'no-use-before-define': 'off',
|
||||||
|
'no-param-reassign': ['warn', { props: false }],
|
||||||
|
'max-len': [
|
||||||
|
2,
|
||||||
|
{
|
||||||
|
ignoreComments: true,
|
||||||
|
ignoreUrls: true,
|
||||||
|
code: 140,
|
||||||
|
ignorePattern: '^(import\\s.+\\sfrom\\s.+|\\} from)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Правила форматирования (Prettier)
|
||||||
|
*/
|
||||||
|
|
||||||
|
'prettier/prettier': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
semi: false,
|
||||||
|
singleQuote: true,
|
||||||
|
jsxSingleQuote: true,
|
||||||
|
trailingComma: 'es5',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Правила форматирования (Prettier)
|
|
||||||
*/
|
|
||||||
|
|
||||||
'prettier/prettier': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
semi: false,
|
|
||||||
singleQuote: true,
|
|
||||||
jsxSingleQuote: true,
|
|
||||||
trailingComma: 'es5',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Переопределение правил для JavaScript файлов
|
* Переопределение правил для JavaScript файлов
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
files: ['**/*.js'],
|
files: ['**/*.js'],
|
||||||
rules: {
|
rules: {
|
||||||
'consistent-return': 'off',
|
'consistent-return': 'off',
|
||||||
'@typescript-eslint/no-var-requires': 'off',
|
'@typescript-eslint/no-var-requires': 'off',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Переопределение правил для тестов и сторибуков
|
* Переопределение правил для тестов и сторибуков
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
files: ['**/src/**/*.{test,stories}.{ts,tsx}'],
|
files: ['**/src/**/*.{test,stories}.{ts,tsx}'],
|
||||||
rules: {
|
rules: {
|
||||||
'max-len': 'off',
|
'max-len': 'off',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -52,5 +52,6 @@ module.exports = {
|
|||||||
'order/order': selectorOrdering,
|
'order/order': selectorOrdering,
|
||||||
'order/properties-order': propertyOrdering,
|
'order/properties-order': propertyOrdering,
|
||||||
'declaration-empty-line-before': null,
|
'declaration-empty-line-before': null,
|
||||||
|
'no-descending-specificity': null, // Отключаем из-за конфликта с order/order
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
],
|
||||||
"*": [
|
"*": [
|
||||||
"./src/*"
|
"./src/*"
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user