From 32ff47731c9c7f292905c6a0b2a86565cc65fb09 Mon Sep 17 00:00:00 2001 From: Crimson Date: Sun, 30 Aug 2026 07:41:31 +0500 Subject: [PATCH] =?UTF-8?q?build(frontend):=20=D1=83=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BD=D0=B5=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B6=D0=B8=D0=B2=D0=B0=D0=B5=D0=BC=D1=8B=D0=B9=20=D0=BF=D0=BB?= =?UTF-8?q?=D0=B0=D0=B3=D0=B8=D0=BD=20=D0=B8=D0=BA=D0=BE=D0=BD=D0=BE=D0=BA?= =?UTF-8?q?=20=D0=B8=20EOL-=D0=BB=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=8B,=20a?= =?UTF-8?q?udit=20=D0=B4=D0=BE=20=D0=BD=D1=83=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vite-plugin-svg-icons не обновлялся с 2022 года и был единственным источником половины оставшихся предупреждений: svgo 2.8, postcss 5.2.18, braces 2.3.2 и image-size 0.5.5 — у последней advisory прямо сообщает `Patched versions: <0.0.0`, то есть исправленной версии не существует. Задача, которую он решал, заняла один модуль: import.meta.glob собирает семнадцать локальных SVG в скрытый спрайт со . Компонентный подход (unplugin-icons) здесь не подходит — имя иконки часто вычисляется в рантайме (onlyOneChild.meta.icon, isFullscreen ? ... : ...), а поиск по id нужен именно для этого. API не изменился. Проверка на реальных ассетах поймала то, что иначе уехало бы в релиз: три иконки из семнадцати не объявляют viewBox, задавая только width/height. Без viewBox рисует иконку в натуральную величину и обрезает её. Плагин синтезировал viewBox сам; теперь это делает sprite.ts, а инвариант закреплён приёмкой — иконка без обоих способов задать координаты роняет сборку. Отдельно: typecheck поймал две ошибки уже в самом sprite.ts (SVGSVGElement против HTMLElement из getElementById). Ровно то, ради чего он возвращался. eslint 8 объявлен EOL и оставался вторым источником предупреждений. Переход на eslint 10 потребовал flat config: eslintrc в 9 работает только через переменную окружения, а в 10 удалён, поэтому обновление версии без смены формата было бы отсрочкой на релиз. Набор правил сохранён прежним; .eslintignore свёрнут в ignores, как требует новый формат. Проверено, что flat config действительно линтит, а не молча пропускает: пробный файл с неиспользуемой переменной и необъявленным именем даёт обе ошибки и в .ts, и в .vue. Оставшиеся предупреждения приходили из графов самих eslint 10 и stylelint 17, то есть уже последних версий, — закрыты pnpm.overrides. Override для ajv ограничен `table>ajv`: глобальный ломал eslint, который использует ajv 6. pnpm audit по всему графу: 33 предупреждения -> 0. typecheck/eslint/stylelint/build: 0. go build и go test с встроенным dist: OK. --- apps/frontend/.eslintignore | 13 - apps/frontend/.eslintrc.cjs | 31 - apps/frontend/eslint.config.mjs | 96 + apps/frontend/package.json | 22 +- apps/frontend/pnpm-lock.yaml | 1909 +++-------------- .../frontend/src/components/SvgIcon/sprite.ts | 134 ++ apps/frontend/src/main.ts | 4 +- apps/frontend/vite.config.ts | 9 - tools/build/lib/acceptance.sh | 36 + 9 files changed, 567 insertions(+), 1687 deletions(-) delete mode 100644 apps/frontend/.eslintignore delete mode 100644 apps/frontend/.eslintrc.cjs create mode 100644 apps/frontend/eslint.config.mjs create mode 100644 apps/frontend/src/components/SvgIcon/sprite.ts diff --git a/apps/frontend/.eslintignore b/apps/frontend/.eslintignore deleted file mode 100644 index 68aacde..0000000 --- a/apps/frontend/.eslintignore +++ /dev/null @@ -1,13 +0,0 @@ -dist -node_modules -public -.vscode -.idea -*.sh -*.md - -src/assets - -.eslintrc.cjs -.prettierrc.cjs -.stylelintrc.cjs diff --git a/apps/frontend/.eslintrc.cjs b/apps/frontend/.eslintrc.cjs deleted file mode 100644 index 097d04d..0000000 --- a/apps/frontend/.eslintrc.cjs +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true, - node: true, - }, - parser: "vue-eslint-parser", // https://eslint.vuejs.org/user-guide/#bundle-configurations - extends: [ - "eslint:recommended", - "plugin:vue/vue3-essential", - "plugin:@typescript-eslint/recommended", - "./.eslintrc-auto-import.json", - ], - parserOptions: { - ecmaVersion: "latest", - sourceType: "module", - parser: "@typescript-eslint/parser", - }, - plugins: ["vue", "@typescript-eslint"], - rules: { - "vue/multi-word-component-names": "off", // Disable multi-word component name requirement: https://eslint.vuejs.org/rules/multi-word-component-names.html - "@typescript-eslint/no-empty-function": "off", // Disable empty function checks - "@typescript-eslint/no-explicit-any": "off", // Disable warnings for any - "vue/no-v-model-argument": "off", - "@typescript-eslint/no-non-null-assertion": "off", - }, // https://eslint.org/docs/latest/use/configure/language-options#specifying-globals - globals: { - DialogType: "readonly", - OptionType: "readonly", - }, -}; diff --git a/apps/frontend/eslint.config.mjs b/apps/frontend/eslint.config.mjs new file mode 100644 index 0000000..c726089 --- /dev/null +++ b/apps/frontend/eslint.config.mjs @@ -0,0 +1,96 @@ +import { createRequire } from "node:module"; + +import js from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginVue from "eslint-plugin-vue"; +import prettier from "eslint-config-prettier"; +import vueParser from "vue-eslint-parser"; + +/** + * Конфигурация ESLint во flat-формате. + * + * Заменяет `.eslintrc.cjs`. Причина не в моде на формат: eslint 8 объявлен + * EOL, перестал получать исправления и оставался последним источником десятка + * предупреждений `pnpm audit` в проекте (minimatch, brace-expansion, js-yaml, + * flatted — всё в его собственном графе). Eslintrc-формат в eslint 9 работает + * только через переменную окружения, а в 10 удалён вовсе, поэтому обновление + * версии без перехода на flat-config было бы отсрочкой на один релиз. + * + * Набор правил сохранён ровно тем же, что был в `.eslintrc.cjs`: перевод + * формата не место для изменения политики линтинга. + */ + +// Глобальные имена авто-импорта генерирует unplugin-auto-import в +// eslintrc-формате (`{ globals: { ref: true, ... } }`). Flat-config такой файл +// через `extends` не подключает, поэтому список читается напрямую — источник +// истины остаётся один, и он по-прежнему пересоздаётся сборкой. +const require = createRequire(import.meta.url); +const autoImportGlobals = require("./.eslintrc-auto-import.json").globals; + +export default tseslint.config( + { + // Перенесено из .eslintignore: eslint 9 этот файл больше не читает, и + // список исключений обязан жить в самой конфигурации. + // + // src/assets — SVG и изображения; src/types/*.d.ts — объявления, которые + // генерируют unplugin-auto-import и unplugin-vue-components, править их + // вручную нельзя, а замечания линтера по ним только шумят. + ignores: [ + "dist/**", + "node_modules/**", + "public/**", + "src/assets/**", + "src/types/*.d.ts", + ], + }, + + js.configs.recommended, + ...tseslint.configs.recommended, + ...pluginVue.configs["flat/essential"], + + { + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + globals: { + ...globals.browser, + ...globals.node, + ...autoImportGlobals, + // Объявлены в src/types/global.d.ts и используются как глобальные типы. + DialogType: "readonly", + OptionType: "readonly", + }, + }, + rules: { + // Имя компонента из одного слова — устоявшееся соглашение этого проекта. + "vue/multi-word-component-names": "off", + "vue/no-v-model-argument": "off", + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-non-null-assertion": "off", + }, + }, + + { + // .vue разбирает vue-eslint-parser, а