build(frontend): убрать неподдерживаемый плагин иконок и EOL-линтеры, audit до нуля
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 в скрытый спрайт со <symbol>. Компонентный подход (unplugin-icons) здесь не подходит — имя иконки часто вычисляется в рантайме (onlyOneChild.meta.icon, isFullscreen ? ... : ...), а поиск по id нужен именно для этого. API <svg-icon icon-class="..."> не изменился. Проверка на реальных ассетах поймала то, что иначе уехало бы в релиз: три иконки из семнадцати не объявляют viewBox, задавая только width/height. Без viewBox <use> рисует иконку в натуральную величину и обрезает её. Плагин синтезировал 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.
This commit is contained in:
@@ -187,6 +187,42 @@ run_fix20_acceptance_subset() {
|
||||
log_step "Acceptance: bootstrap peer can pass auth smoke"
|
||||
grep -q 'quota := int64(-1)' apps/dao/sqlite.go || fail "acceptance: bootstrap peer quota must be unlimited (-1), otherwise install auth smoke fails"
|
||||
|
||||
log_step "Acceptance: local SVG icons are rendered from an in-repo sprite"
|
||||
# vite-plugin-svg-icons убран: он не обновлялся с 2022 года и тянул svgo 2.8,
|
||||
# postcss 5.2.18 и image-size 0.5.5, у последней advisory прямо сообщает
|
||||
# `Patched versions: <0.0.0` — исправленной версии не существует.
|
||||
! grep -q '"vite-plugin-svg-icons"' apps/frontend/package.json \
|
||||
|| fail "acceptance: неподдерживаемый vite-plugin-svg-icons вернулся в зависимости"
|
||||
! grep -rq 'virtual:svg-icons-register' apps/frontend/src \
|
||||
|| fail "acceptance: виртуальный модуль удалённого плагина иконок вернулся"
|
||||
grep -q 'registerSvgIcons' apps/frontend/src/main.ts \
|
||||
|| fail "acceptance: спрайт локальных иконок не регистрируется при старте приложения"
|
||||
|
||||
# Каждая иконка обязана давать symbol с viewBox.
|
||||
#
|
||||
# Без viewBox `<use>` не знает систему координат и рисует иконку в натуральную
|
||||
# величину, обрезая её по размеру родительского svg. Три иконки из
|
||||
# семнадцати его не объявляют — для них viewBox синтезируется из width/height,
|
||||
# как это делал заменённый плагин. Проверка сторожит именно ассеты: иконка,
|
||||
# добавленная без обоих способов задать координаты, иначе сломала бы
|
||||
# отрисовку молча.
|
||||
"$BUN_BIN" -e '
|
||||
const fs = require("node:fs");
|
||||
const dir = "apps/frontend/src/assets/icons";
|
||||
const files = fs.readdirSync(dir).filter((f) => f.endsWith(".svg"));
|
||||
if (files.length === 0) throw new Error("каталог локальных иконок пуст");
|
||||
const broken = [];
|
||||
for (const file of files) {
|
||||
const raw = fs.readFileSync(`${dir}/${file}`, "utf8");
|
||||
const openTag = raw.replace(/<\?xml[\s\S]*?\?>/gi, "").replace(/<!DOCTYPE[\s\S]*?>/gi, "").match(/<svg\b[^>]*>/i);
|
||||
if (!openTag) { broken.push(`${file}: нет корневого <svg>`); continue; }
|
||||
const hasViewBox = /viewBox="[^"]+"/i.test(openTag[0]);
|
||||
const hasSize = /width="[\d.]+[a-z%]*"/i.test(openTag[0]) && /height="[\d.]+[a-z%]*"/i.test(openTag[0]);
|
||||
if (!hasViewBox && !hasSize) broken.push(`${file}: нет ни viewBox, ни пары width/height`);
|
||||
}
|
||||
if (broken.length) throw new Error("иконки без системы координат:\n" + broken.join("\n"));
|
||||
' || fail "acceptance: локальная иконка не даёт корректный <symbol> для спрайта"
|
||||
|
||||
log_step "Acceptance: frontend i18n does not touch Pinia at module import"
|
||||
! grep -q 'useAppStore' apps/frontend/src/lang/index.ts || fail "acceptance: lang/index.ts must not import/use Pinia store"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user