Files
easy-png-tools2/docs/plan-split-into-parts.md
T

83 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# План: инструмент «Разрезать PNG на части» (split-into-parts-png)
> Статус: **в работе** (2026-09). Первый потребитель механизма «результат =
> набор файлов» (1 → many). Общий процесс таких инструментов — отдельная задача
> в `docs/backlog.md`.
## Цель
Пользователь загружает одну картинку, выбирает число столбцов и строк, картинка
разрезается на равномерные части. Результат — набор PNG-файлов, скачивается
ZIP-архивом.
## Решения
- **Неравномерное деление:** канвас дополняется прозрачным до кратного размера
(`pieceW = ceil(w / cols)`, `newW = pieceW * cols`), все части строго равные,
картинка покрывается целиком.
- **Дефолт схемы:** 2 × 2.
- **Zip-библиотека:** `fflate` (zero deps, малый размер), скачивание из UI-слоя
(`encode()` требует DOM).
- **Результат инструмента:** `result: "files"` — терминальный тип, в пайплайн
(следующий шаг) не передаётся.
## Шаги
1. **Зависимость:** `fflate` в `web/package.json`.
2. **`registry/types.ts`:** `RESULT_KINDS.files`, тип `ToolImageFile`,
`FileResult`, расширение `ToolResult = PixelImage | string | FileResult`.
3. **`core/geometry.ts`:** `splitToParts(img, columns, rows)` — padding + сетка
через `crop`.
4. **`web/src/lib/zip.ts` (новый):** `downloadZip(files, zipName)` через
`zipSync`.
5. **`core/errors.ts`:** ключ `errors.tooManyParts` (страховочный лимит
cols·rows ≤ 1000; при максимуме 6×6 недостижим).
6. **`registry/geometry.ts`:** схема (`columns`, `rows`, дефолт 2×2, min 1,
max 6 — максимум 36 частей) + entry `split-into-parts-png` в `geometryEntries`.
7. **Executor:** сериализация/десериализация `FileResult` в `executor.worker.ts`
и тип ветки в `executor.ts`.
8. **UI:** `SchemaToolView.svelte` (`fileResult`, Download → zip),
`SchemaPreview.svelte` (canDownload для files), `SchemaResultTile.svelte`
(сетка-превью частей, мета «N parts / ZIP»).
9. **i18n:** переводы в `ru.ts`/`en.ts` **не добавляем** — словари `tools`
привязаны к v1-реестру (тест «нет лишних ключей»), а preview берёт заголовки
из registry (EN). Перевод придёт вместе с беклог-задачей «i18n в preview».
Поиск по id/заголовку работает из registry.
10. **Тесты:** юнит `splitToParts`, registry (result: "files"), i18n coverage.
11. **Docs:** `docs/backlog.md` (задача «процесс 1 → many и many → 1», отметить
пункт 11 «Мультифайловый вывод»), `docs/tools-map.md` (перенос из идей).
## Файлы
| Файл | Изменение |
| ------------------------------------------------ | ----------------------------------------------------------------- |
| `web/package.json` | `+ fflate` (dependencies) |
| `web/src/lib/registry/types.ts` | `RESULT_KINDS.files`, `ToolImageFile`, `FileResult`, `ToolResult` |
| `web/src/lib/core/geometry.ts` | `splitToParts()` |
| `web/src/lib/zip.ts` | **новый**`downloadZip()` |
| `web/src/lib/core/errors.ts` | `errors.tooManyParts` |
| `web/src/lib/registry/geometry.ts` | schema + `splitPartsTool` |
| `web/src/lib/executor/executor.worker.ts` | ветка `FileResult` |
| `web/src/lib/executor/executor.ts` | тип ветки `FileResult` |
| `web/src/lib/components/SchemaToolView.svelte` | `fileResult`, download → zip |
| `web/src/lib/components/SchemaPreview.svelte` | props `fileResult`, `canDownload` |
| `web/src/lib/components/SchemaResultTile.svelte` | сетка частей, «N parts» |
| `web/src/lib/i18n/ru.ts`, `en.ts` | записи инструмента |
## Нейминг файлов в ZIP
`part-01-01.png``part-<row>-<col>.png` (row, col нумеруются с 1, ведущий ноль
для выравнивания по числу строк/столбцов).
## Верификация
```bash
pnpm --dir web exec svelte-check --tsconfig ./tsconfig.json
pnpm --dir web test
pnpm --dir web lint
```
Ручная проверка: PNG не кратного размера (например 101×77), 3×2 → 6 частей
одинакового размера, скачивается ZIP; на кратном размере (100×80, 3×2) padding
= 0.