mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
docs: update plans, backlog
This commit is contained in:
+70
-36
@@ -23,7 +23,7 @@ web/src/lib/
|
||||
web/src/routes/
|
||||
+page.svelte # главная
|
||||
list-tools/ # каталог
|
||||
tools/[id]/ # страница инструмента
|
||||
tools/[id]/ # страница инструмента (адрес = id записи)
|
||||
kit/ # витрина компонентов (production, но исключена из i18n-гейта)
|
||||
```
|
||||
|
||||
@@ -32,6 +32,21 @@ web/src/routes/
|
||||
`registry/**` описывает данные и знает только `core/**` и `registry-schema.ts`.
|
||||
Нарушение этого порядка — повод не заводить импорт, а инвертировать зависимость.
|
||||
|
||||
### Чего в коде нет
|
||||
|
||||
Страница инструмента работает ровно с одним инструментом: загрузил файл →
|
||||
применил одну запись реестра → скачал результат. Отсутствуют:
|
||||
|
||||
- **Пайплайн / цепочки шагов** — модуля нет, состояния нет, localStorage для
|
||||
него нет. `docs/roadmap.md` описывает его как отдельную фазу, а не как
|
||||
поставленное. Под будущую фазу зарезервированы `components/StepCard.svelte`
|
||||
(сейчас импортируется только витриной `/kit`) и ключи `chain.*`,
|
||||
`errors.badPipelineShape`, `errors.noSteps`.
|
||||
- **Разделения `id` и `slug`** — раздел 3.
|
||||
|
||||
Задачи по обоим пунктам — в `docs/backlog.md`; архитектурные решения по
|
||||
пайплайну — `docs/roadmap.md`.
|
||||
|
||||
## 2. Поток данных
|
||||
|
||||
```txt
|
||||
@@ -62,8 +77,8 @@ registry/*.ts ──(TOOLS: ToolEntry[])
|
||||
|
||||
Ключевые решения:
|
||||
|
||||
- **Реестр — единственный источник истины.** Страница, форма и пайплайн строятся
|
||||
из записи; новый инструмент = новая запись + функция `run`.
|
||||
- **Реестр — единственный источник истины.** Страница и форма строятся из
|
||||
записи; новый инструмент = новая запись + функция `run`.
|
||||
- **Исполнение идёт только через `executor.execute`.** Компоненты не зовут
|
||||
`tool.run` напрямую — иначе нельзя перенести тяжёлое в worker/wasm без правки
|
||||
вызывающего кода.
|
||||
@@ -76,22 +91,35 @@ registry/*.ts ──(TOOLS: ToolEntry[])
|
||||
|
||||
`ToolEntry` (`web/src/lib/registry/types.ts`):
|
||||
|
||||
| Поле | Смысл |
|
||||
| ------------- | ------------------------------------------------------------ |
|
||||
| `id` | уникальный ключ; он же URL-anchor и ключ в пайплайне |
|
||||
| `title` | EN-строка реестра, переводится через `tools.*.title` |
|
||||
| `description` | EN-строка реестра, переводится через `tools.*.description` |
|
||||
| `category` | id из `categories.ts` |
|
||||
| `schema` | `toolSchema({ fields, layout?, meta? })` |
|
||||
| `input` | `"image" \| "text" \| "none"` — что ждёт инструмент на входе |
|
||||
| `result` | `"image" \| "text" \| "verdict" \| "files"` — что отдаёт |
|
||||
| `output` | mime/ext/quality для download (не у всех инструментов) |
|
||||
| `run(ctx)` | чистая функция: `ctx` → `ToolResult` |
|
||||
| Поле | Смысл |
|
||||
| ------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| `id` | идентичность инструмента **и** публичный адрес `/tools/<id>` **и** база имени скачиваемого файла |
|
||||
| `title` | EN-строка реестра, переводится через `tools.*.title` |
|
||||
| `description` | EN-строка реестра, переводится через `tools.*.description` |
|
||||
| `category` | id из `categories.ts` |
|
||||
| `schema` | `toolSchema({ fields, layout?, meta? })` |
|
||||
| `input` | `"image" \| "text" \| "none"` — что ждёт инструмент на входе |
|
||||
| `result` | `"image" \| "text" \| "verdict" \| "files"` — что отдаёт |
|
||||
| `domOnly` | инструмент требует DOM (canvas); превью-executor запускает его напрямую, минуя worker |
|
||||
| `output` | mime/ext/quality для download (не у всех инструментов) |
|
||||
| `icon` | id иконки из `tool-icons.ts` |
|
||||
| `run(ctx)` | единственный метод: `ctx` → `ToolResult` |
|
||||
|
||||
Отдельного поля `slug` **нет**: адрес страницы, ключ i18n (`tools.<id>.*`) и имя
|
||||
файла скачивания — это один и тот же `id`. Инструмент работает с любым
|
||||
поддержанным форматом, но страница держит png-интент, поэтому `-png` живёт
|
||||
внутри `id` (`id: "crop-png"` → `/tools/crop-png` → `crop-png.png`). Следствие:
|
||||
переименование `id` меняет адрес страницы, ключи `tools.*` и имя файла.
|
||||
|
||||
Хелперы `genTool` / `imgTool` / `textGen` из `types.ts` задают `run` для типовых
|
||||
случаев (приведение типа результата), чтобы запись не повторяла обвязку. `TOOLS`
|
||||
собирается в `registry/index.ts` из восьми групп; `getTool(id)` — единственный
|
||||
способ достать запись по id.
|
||||
способ достать запись, `registry.test.ts` проверяет уникальность `id`.
|
||||
|
||||
Разделение `id` (внутреннее имя) и `slug` (адрес) — решённое, но **не
|
||||
реализованное** решение: задача и порядок волн в `docs/backlog.md`, раздел
|
||||
«Мелочи всякие». До её выполнения этот документ описывает текущее состояние, а
|
||||
id и slug совпадают.
|
||||
|
||||
## 4. Схема параметров
|
||||
|
||||
@@ -133,15 +161,16 @@ EN-ключей `tools.*` и словарь-переводчик. Инвариа
|
||||
|
||||
## 7. Точки расширения
|
||||
|
||||
| Задача | Где править |
|
||||
| ------------------------------ | ----------------------------------------------------------------- |
|
||||
| Новый инструмент | запись в `registry/<group>.ts` + i18n-ключи + тесты (рецепт ниже) |
|
||||
| Новый вид поля | `registry-schema.ts` + контрол + `FIELDS` (раздел 4) |
|
||||
| Новый маршрут/страница | `web/src/routes/**` + ссылка в каталоге |
|
||||
| Новый визуальный элемент | компонент в `components/**` по образцу `ui/` или `layout/` |
|
||||
| Новый дизайн-токен | `web/src/app.css` (только там) + потребитель сразу |
|
||||
| Тяжёлая операция → worker/wasm | `executor/**`, без правок компонентов |
|
||||
| Мультифайловый результат | `result: "files"` + `zip.ts` |
|
||||
| Задача | Где править |
|
||||
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Новый инструмент | запись в `registry/<group>.ts` + i18n-ключи + тесты (рецепт ниже) |
|
||||
| Смена `id` | запись реестра + i18n-ключи `tools.*` + `tool-icons.ts` + хардкод id в тестах, `/kit` и e2e; меняется адрес страницы — операция с SEO-последствиями, не часть обычной задачи |
|
||||
| Новый вид поля | `registry-schema.ts` + контрол + `FIELDS` (раздел 4) |
|
||||
| Новый маршрут/страница | `web/src/routes/**` + ссылка в каталоге |
|
||||
| Новый визуальный элемент | компонент в `components/**` по образцу `ui/` или `layout/` |
|
||||
| Новый дизайн-токен | `web/src/app.css` (только там) + потребитель сразу |
|
||||
| Тяжёлая операция → worker/wasm | `executor/**`, без правок компонентов |
|
||||
| Мультифайловый результат | `result: "files"` + `zip.ts` |
|
||||
|
||||
## 8. Рецепт: добавить инструмент
|
||||
|
||||
@@ -150,22 +179,27 @@ EN-ключей `tools.*` и словарь-переводчик. Инвариа
|
||||
2. **Выбрать группу** (`geometry`/`alpha`/`color`/`convert`/`filters`/
|
||||
`generate`/`text`/`analyze`) и положить запись в её экспорт; при новой
|
||||
категории — сначала `categories.ts`.
|
||||
3. **Описать схему** через `field.*`, задать `layout`, если поля нужно
|
||||
3. **Задать `id`.** Он же адрес страницы, он же ключ i18n, он же база имени
|
||||
скачиваемого файла. Страница держит png-интент, поэтому суффикс `-png` входит
|
||||
в `id` (`crop-png`, `resize-png`) — это осознанно, отдельного поля `slug` в
|
||||
реестре нет (раздел 3).
|
||||
4. **Описать схему** через `field.*`, задать `layout`, если поля нужно
|
||||
сгруппировать.
|
||||
4. **Написать `run`** поверх `core/*`; пиксельные операции — чистые функции в
|
||||
5. **Написать `run`** поверх `core/*`; пиксельные операции — чистые функции в
|
||||
`core/`, без DOM.
|
||||
5. **Проверить обязательные контракты** для нового id: entry попадает в `TOOLS`,
|
||||
страница `/tools/<id>` prerender-ится, `input`/`result` согласованы с тем,
|
||||
что делает `run`.
|
||||
6. **Добавить i18n-ключи во все локали** сразу.
|
||||
7. **Тесты:** unit — в `registry/*.test.ts` или рядом с `core`-функцией;
|
||||
6. **Проверить обязательные контракты** для новой записи: она попадает в
|
||||
`TOOLS`, страница `/tools/<id>` prerender-ится, `input`/`result` согласованы
|
||||
с тем, что делает `run`.
|
||||
7. **Добавить i18n-ключи во все локали** сразу (ключ — по `id`).
|
||||
8. **Тесты:** unit — в `registry/*.test.ts` или рядом с `core`-функцией;
|
||||
e2e-smoke — существующий spec по типу `input`/`result` (правила —
|
||||
`docs/testing-strategy.md`).
|
||||
8. **Обновить `docs/tools-map.md`:** новый инструмент обязателен в разделе
|
||||
«Реализовано», формат строки — в шапке раздела. Проверяет
|
||||
`web/src/lib/registry/tools-map-doc.test.ts`: отсутствующий в карте id и
|
||||
несуществующий в реестре id роняют тест. Обоснование и границы автоматизации
|
||||
— `docs/decisions.md`, раздел 4.
|
||||
9. **Обновить `docs/tools-map.md`:** новая страница обязательна в разделе
|
||||
«Реализовано», формат строки — в шапке раздела. Карта перечисляет **`id`**
|
||||
реестра, которые одновременно являются адресами страниц. Проверяет
|
||||
`web/src/lib/registry/tools-map-doc.test.ts`: id без инструмента и инструмент
|
||||
без записи в карте роняют тест. Обоснование и границы автоматизации —
|
||||
`docs/decisions.md`, раздел 4.
|
||||
|
||||
Ожидаемый минимум проверок: `pnpm --dir web check` и `pnpm --dir web test`; для
|
||||
инструмента, меняющего пользовательский поток, — e2e (см. раздел 3
|
||||
|
||||
Reference in New Issue
Block a user