mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
chore: update lint rules, some docs terms
This commit is contained in:
@@ -61,8 +61,7 @@
|
|||||||
|
|
||||||
## Границы изменений
|
## Границы изменений
|
||||||
|
|
||||||
- Production-UI — `web/src/routes/**` и `web/src/lib/components/**`. Старый UI
|
- Production-UI — `web/src/routes/**` и `web/src/lib/components/**`.
|
||||||
(`/v1/**`) удалён и не возвращается.
|
|
||||||
- `web/src/lib/core/**` и `web/src/lib/theme.svelte.ts` — общие модули: их
|
- `web/src/lib/core/**` и `web/src/lib/theme.svelte.ts` — общие модули: их
|
||||||
правка проверяется unit-тестами и smoke-сценариями production-потребителей.
|
правка проверяется unit-тестами и smoke-сценариями production-потребителей.
|
||||||
- Направление зависимостей, точки расширения и рецепт правки (инструмент, вид
|
- Направление зависимостей, точки расширения и рецепт правки (инструмент, вид
|
||||||
|
|||||||
+2
-6
@@ -14,10 +14,6 @@
|
|||||||
|
|
||||||
## lint и прочие правила
|
## lint и прочие правила
|
||||||
|
|
||||||
- [ ] расширить `i18n/no-hardcoded-user-text` на `web/src/routes/**`: сейчас
|
|
||||||
правило навешено только на `components/**` (без `/kit`), поэтому
|
|
||||||
захардкоженный текст в `routes/**` проходит молча (`web/eslint.config.js`,
|
|
||||||
`web/eslint-plugins/README.md`)
|
|
||||||
- [ ] `tseslint.config(...)` deprecated: сигнатура
|
- [ ] `tseslint.config(...)` deprecated: сигнатура
|
||||||
`(...configs: InfiniteDepthConfigWithExtends[]): ConfigArray` помечена
|
`(...configs: InfiniteDepthConfigWithExtends[]): ConfigArray` помечена
|
||||||
устаревшей, нужен переход на `defineConfig` из `typescript-eslint` —
|
устаревшей, нужен переход на `defineConfig` из `typescript-eslint` —
|
||||||
@@ -103,8 +99,8 @@
|
|||||||
|
|
||||||
## SEO/GEO
|
## SEO/GEO
|
||||||
|
|
||||||
Общий план: `docs/plan-seo.md` (S0–S4). Переезд preview на реальные маршруты
|
Общий план: `docs/plan-seo.md` (S0–S4). Старт возможен — пока только domain-free
|
||||||
выполнен; старт возможен — пока только domain-free часть S1.
|
часть S1.
|
||||||
|
|
||||||
- [ ] переименование бренда + домен: чек-лист в локальном плане
|
- [ ] переименование бренда + домен: чек-лист в локальном плане
|
||||||
`docs/plan-domain.local.md` (вне git, имя домена в репо не публикуется;
|
`docs/plan-domain.local.md` (вне git, имя домена в репо не публикуется;
|
||||||
|
|||||||
+6
-7
@@ -1,12 +1,11 @@
|
|||||||
# План: SEO + GEO — индексация и конкуренция в image tools
|
# План: SEO + GEO — индексация и конкуренция в image tools
|
||||||
|
|
||||||
> **Статус (2026-09-11; уточнено 2026-09-27):** план к выполнению. Переезд
|
> **Статус (2026-09-11; уточнено 2026-09-27):** план к выполнению; маршруты
|
||||||
> `preview/*` на реальные маршруты выполнен. **`noindex` на страницах
|
> инструментов — корневые (`/tools/[id]`). **`noindex` на страницах инструментов
|
||||||
> инструментов не выставляется** — снимать нечего, каталог открыт для
|
> не выставляется** — снимать нечего, каталог открыт для индексации; запрет
|
||||||
> индексации; запрет индексации держится только на служебных путях
|
> индексации держится только на служебных путях (`robots.txt`). Задачи S1
|
||||||
> (`robots.txt`). Домен не был блокером переезда (см. §6). Задачи S1 разбиты на
|
> разбиты на domain-free (можно делать параллельно с покупкой домена) и
|
||||||
> domain-free (можно делать параллельно с покупкой домена) и domain-required
|
> domain-required (после покупки и настройки домена).
|
||||||
> (после покупки и настройки домена).
|
|
||||||
>
|
>
|
||||||
> **Цель:** каждая страница инструмента — индексируемый лендинг под конкретный
|
> **Цель:** каждая страница инструмента — индексируемый лендинг под конкретный
|
||||||
> интент («crop png», «make png transparent», «jpg to png»…), конкуренция с
|
> интент («crop png», «make png transparent», «jpg to png»…), конкуренция с
|
||||||
|
|||||||
+7
-8
@@ -1,14 +1,13 @@
|
|||||||
# План развития: easy-png-tools
|
# План развития: easy-png-tools
|
||||||
|
|
||||||
> **Статус (2026-09):** Фаза 1 (полноценный TS-сайт) в основном выполнена — сайт
|
> **Статус (2026-09):** Фаза 1 (полноценный TS-сайт) в основном выполнена — сайт
|
||||||
> живёт, каталог переведён в типизированный `registry`, новый дизайн стал
|
> живёт, каталог переведён в типизированный `registry`, production UI — корневые
|
||||||
> единственным production UI на корневых маршрутах, UI-v1 удалён. Tech debt не
|
> маршруты. Tech debt не закрыт полностью; состав quality-проверок —
|
||||||
> закрыт полностью; состав quality-проверок — `docs/quality-gates.md`,
|
> `docs/quality-gates.md`, архитектура кода — `docs/architecture.md`, список
|
||||||
> архитектура кода — `docs/architecture.md`, список инструментов —
|
> инструментов — `docs/tools-map.md`. Текущий фокус: SEO S1-free
|
||||||
> `docs/tools-map.md`. Текущий фокус: SEO S1-free (`docs/plan-seo.md`) +
|
> (`docs/plan-seo.md`) + продуктовые задачи из `docs/backlog.md`. Домен нужен
|
||||||
> продуктовые задачи из `docs/backlog.md`. Домен нужен для SEO (`plan-seo.md`,
|
> для SEO (`plan-seo.md`, S1-domain). Фазы 2–8 — будущие; фазы 9–10 спланированы
|
||||||
> S1-domain). Фазы 2–8 — будущие; фазы 9–10 спланированы в
|
> в `docs/plan-platform.md`.
|
||||||
> `docs/plan-platform.md`.
|
|
||||||
>
|
>
|
||||||
> **Нумерация фаз этого документа не совпадает с волнами разработки** (`Q*`/`C*`
|
> **Нумерация фаз этого документа не совпадает с волнами разработки** (`Q*`/`C*`
|
||||||
> в других документах) и не используется как идентификатор задач: ссылаться на
|
> в других документах) и не используется как идентификатор задач: ссылаться на
|
||||||
|
|||||||
@@ -42,9 +42,13 @@
|
|||||||
`__fixtures__/` дописать их туда же.
|
`__fixtures__/` дописать их туда же.
|
||||||
- design-tokens правила применяются к тем же scoped-путям
|
- design-tokens правила применяются к тем же scoped-путям
|
||||||
(`src/lib/components/**`, `src/routes/**`).
|
(`src/lib/components/**`, `src/routes/**`).
|
||||||
- `i18n/no-hardcoded-user-text` применяется к `src/lib/components/**` (`/kit`
|
- `i18n/no-hardcoded-user-text` применяется к обоим scoped-путям
|
||||||
исключён как витрина с намеренно hardcoded-подписями) и настраивается опцией
|
(`src/lib/components/**` и `src/routes/**`): хардкод в `+page.svelte` и
|
||||||
`allowWords` —brand не хардкодится в правиле.
|
`+layout.svelte` — такой же production-UI. Исключение одно — `/kit`, витрина с
|
||||||
|
намеренно латинскими подписями; выключается отдельным объектом конфига с
|
||||||
|
`files: ["**/src/routes/kit/**/*.svelte"]`, потому что негативные паттерны в
|
||||||
|
`files` не сужают область действия правила. Опция `allowWords` — brand не
|
||||||
|
хардкодится в правиле.
|
||||||
|
|
||||||
## Правила плагина design-tokens
|
## Правила плагина design-tokens
|
||||||
|
|
||||||
@@ -115,9 +119,10 @@ report-only (`warn`), baseline — 0 срабатываний.
|
|||||||
`tone`, `type`, `icon`, `size`, `href`, `class`) не проверяются, значения в
|
`tone`, `type`, `icon`, `size`, `href`, `class`) не проверяются, значения в
|
||||||
скобках (`{expr}`) тоже — они считаются в другом месте.
|
скобках (`{expr}`) тоже — они считаются в другом месте.
|
||||||
- Исключения списком, а не «на глаз»: форматы и единицы (`PNG`, `px`, `×`),
|
- Исключения списком, а не «на глаз»: форматы и единицы (`PNG`, `px`, `×`),
|
||||||
имена файлов и версии (`result.png`, `v0.1.0`), размеры (`512×512`),
|
имена файлов и версии (`result.png`, `v0.1.0`, `v1`), размеры (`512×512`),
|
||||||
registry-строки и прочие ALL CAPS идентификаторы (`BACKGROUND`), а также
|
registry-строки и прочие ALL CAPS идентификаторы (`BACKGROUND`), а также
|
||||||
`/kit` — витрина компонентов с намеренно латинскими подписями.
|
`/kit` — витрина компонентов с намеренно латинскими подписями (исключение
|
||||||
|
живёт в `eslint.config.js`, а не в правиле).
|
||||||
- Опция `allowWords: string[]` — brand и прочие собственные имена. Название
|
- Опция `allowWords: string[]` — brand и прочие собственные имена. Название
|
||||||
продукта передаётся конфигом, а не зашито в правило.
|
продукта передаётся конфигом, а не зашито в правило.
|
||||||
- Содержимое `<style>` и `<script>` пропускается: там код, а не копирайт.
|
- Содержимое `<style>` и `<script>` пропускается: там код, а не копирайт.
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
* Options (object, all optional):
|
* Options (object, all optional):
|
||||||
* - allowPaths: dot-path keys excluded from every check.
|
* - allowPaths: dot-path keys excluded from every check.
|
||||||
* - baseLocaleFallback: patterns whose missing keys are allowed in BASE_LOCALE.
|
* - baseLocaleFallback: patterns whose missing keys are allowed in BASE_LOCALE.
|
||||||
* - ignoreMissingPatterns: legacy patterns excluded from missing-key checks.
|
* - ignoreMissingPatterns: patterns temporarily excluded from missing-key
|
||||||
|
* checks.
|
||||||
*/
|
*/
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|||||||
+26
-15
@@ -8,8 +8,8 @@ import designTokens from "./eslint-plugins/index.js";
|
|||||||
import conventionsPlugin from "./eslint-plugins/conventions/index.js";
|
import conventionsPlugin from "./eslint-plugins/conventions/index.js";
|
||||||
import i18nPlugin from "./eslint-plugins/i18n/index.js";
|
import i18nPlugin from "./eslint-plugins/i18n/index.js";
|
||||||
|
|
||||||
// Новый код редизайна: к нему применяем полные recommended-наборы уже сейчас.
|
// Production-UI: к нему применяются полные recommended-наборы.
|
||||||
const newCode = ["**/src/lib/components/**", "**/src/routes/**"];
|
const productionCode = ["**/src/lib/components/**", "**/src/routes/**"];
|
||||||
|
|
||||||
// Инфраструктура линтинга: сами плагины, скрипты и конфиги. Это не
|
// Инфраструктура линтинга: сами плагины, скрипты и конфиги. Это не
|
||||||
// продуктовый код, но всё это влияет на гейты, поэтому к нему тоже
|
// продуктовый код, но всё это влияет на гейты, поэтому к нему тоже
|
||||||
@@ -21,16 +21,16 @@ const toolingFiles = [
|
|||||||
"*.config.js",
|
"*.config.js",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Полные recommended-наборы — только на новый код (см. ниже, блок перед prettier).
|
// Полные recommended-наборы — только на production-код (см. ниже, блок перед prettier).
|
||||||
const jsRecommended = Array.isArray(js.configs.recommended)
|
const jsRecommended = Array.isArray(js.configs.recommended)
|
||||||
? js.configs.recommended
|
? js.configs.recommended
|
||||||
: [js.configs.recommended];
|
: [js.configs.recommended];
|
||||||
const svelteRecommended = Array.isArray(svelte.configs["flat/recommended"])
|
const svelteRecommended = Array.isArray(svelte.configs["flat/recommended"])
|
||||||
? svelte.configs["flat/recommended"]
|
? svelte.configs["flat/recommended"]
|
||||||
: [svelte.configs["flat/recommended"]];
|
: [svelte.configs["flat/recommended"]];
|
||||||
// Svelte-рекомендации применяем только к .svelte-файлам нового кода, иначе
|
// Svelte-рекомендации применяем только к .svelte-файлам production-кода, иначе
|
||||||
// svelte-eslint-parser "съедает" обычные .ts в тех же папках (напр. +page.ts).
|
// svelte-eslint-parser "съедает" обычные .ts в тех же папках (напр. +page.ts).
|
||||||
const newSvelteFiles = [
|
const productionSvelte = [
|
||||||
"**/src/lib/components/**/*.svelte",
|
"**/src/lib/components/**/*.svelte",
|
||||||
"**/src/routes/**/*.svelte",
|
"**/src/routes/**/*.svelte",
|
||||||
];
|
];
|
||||||
@@ -128,7 +128,7 @@ export default tseslint.config(
|
|||||||
// Правило дизайн-токенов: запрет хардкода цветов/размеров в style-блоках.
|
// Правило дизайн-токенов: запрет хардкода цветов/размеров в style-блоках.
|
||||||
// Применяется к новому коду редизайна.
|
// Применяется к новому коду редизайна.
|
||||||
{
|
{
|
||||||
files: newSvelteFiles,
|
files: productionSvelte,
|
||||||
plugins: {
|
plugins: {
|
||||||
"design-tokens": designTokens,
|
"design-tokens": designTokens,
|
||||||
},
|
},
|
||||||
@@ -142,7 +142,7 @@ export default tseslint.config(
|
|||||||
// Конвенция Svelte 5: пропсы через локальный `interface Props` +
|
// Конвенция Svelte 5: пропсы через локальный `interface Props` +
|
||||||
// `let {...}: Props = $props()` (плагин conventions/interface-props).
|
// `let {...}: Props = $props()` (плагин conventions/interface-props).
|
||||||
{
|
{
|
||||||
files: newSvelteFiles,
|
files: productionSvelte,
|
||||||
plugins: {
|
plugins: {
|
||||||
conventions: conventionsPlugin,
|
conventions: conventionsPlugin,
|
||||||
},
|
},
|
||||||
@@ -151,9 +151,9 @@ export default tseslint.config(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Запрет строковых union-алиасов в пользу `as const` объектов
|
// Запрет строковых union-алиасов в пользу `as const` объектов
|
||||||
// (плагин conventions/no-string-union-alias). TS и Svelte-скрипты нового кода.
|
// (плагин conventions/no-string-union-alias). TS и Svelte-скрипты production-кода.
|
||||||
{
|
{
|
||||||
files: newCode,
|
files: productionCode,
|
||||||
plugins: {
|
plugins: {
|
||||||
conventions: conventionsPlugin,
|
conventions: conventionsPlugin,
|
||||||
},
|
},
|
||||||
@@ -182,8 +182,10 @@ export default tseslint.config(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// /kit — витрина компонентов с намеренно захардкоженными подписями.
|
// Хардкод пользовательского текста ловим и в components, и в routes:
|
||||||
files: newSvelteFiles.filter((pattern) => !pattern.includes("routes")),
|
// `+page.svelte`/`+layout.svelte` — такой же production-UI, иначе
|
||||||
|
// захардкоженная строка молча уедет в RU-локаль.
|
||||||
|
files: productionSvelte,
|
||||||
plugins: {
|
plugins: {
|
||||||
i18n: i18nPlugin,
|
i18n: i18nPlugin,
|
||||||
},
|
},
|
||||||
@@ -197,6 +199,15 @@ export default tseslint.config(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Исключение для /kit — витрина компонентов с намеренно латинскими
|
||||||
|
// подписями. Отдельный объект, а не негативный glob в `files` выше:
|
||||||
|
// негативные паттерны не сужают область действия правила.
|
||||||
|
files: ["**/src/routes/kit/**/*.svelte"],
|
||||||
|
rules: {
|
||||||
|
"i18n/no-hardcoded-user-text": "off",
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: toolingFiles,
|
files: toolingFiles,
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
@@ -207,11 +218,11 @@ export default tseslint.config(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Полные recommended-наборы — только на новый код.
|
// Полные recommended-наборы — только на production-код.
|
||||||
...[
|
...[
|
||||||
...jsRecommended.map((cfg) => ({
|
...jsRecommended.map((cfg) => ({
|
||||||
...cfg,
|
...cfg,
|
||||||
files: newCode,
|
files: productionCode,
|
||||||
})),
|
})),
|
||||||
...jsRecommended.map((cfg) => ({
|
...jsRecommended.map((cfg) => ({
|
||||||
...cfg,
|
...cfg,
|
||||||
@@ -219,11 +230,11 @@ export default tseslint.config(
|
|||||||
})),
|
})),
|
||||||
...tseslint.configs.recommended.map((cfg) => ({
|
...tseslint.configs.recommended.map((cfg) => ({
|
||||||
...cfg,
|
...cfg,
|
||||||
files: newCode,
|
files: productionCode,
|
||||||
})),
|
})),
|
||||||
...svelteRecommended.map((cfg) => ({
|
...svelteRecommended.map((cfg) => ({
|
||||||
...cfg,
|
...cfg,
|
||||||
files: newSvelteFiles,
|
files: productionSvelte,
|
||||||
})),
|
})),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user