Files
easy-png-tools2/docs/backlog.md
T
2026-10-11 17:42:46 +05:00

279 lines
27 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.
# Backlog
> Статус: **active**. Открытые задачи. Подробные планы, разбор решений и сырые
> находки — `docs/plan-seo.md`, `docs/plan-platform.md`,
> `docs/plan-fields-audit-fixes.md`, `docs/tools-audit.md`, `docs/decisions.md`.
>
> Все пункты — чекбоксы; нумерация «Идея N» в тексте сквозная по документу и
> сохраняется ради перекрёстных ссылок («идея 4 зависит от идеи 3»). Оценки
> (S/M/L) — оценка труда, не приоритет.
## Тесты и lint
- [ ] правило - только английские комментарии не работает на svelte файлы
- [ ] правило - ограницить комментарии вроде уменьшило простыни из комментариев,
но всё равно они есть и часто пишет очевидные вещи. надо более строгое
правило. может такой вариант: разрешено писать комментарии в коде, но
только внутри функций, название которых начинается с `complex_` или
`tricky_` (или помеченных специальным декоратором/аннотацией).
- [ ] линтер на deprecated иконки возможен? 'FilePlus2' is deprecated.
- [ ] `tseslint.config(...)` deprecated: сигнатура
`(...configs: InfiniteDepthConfigWithExtends[]): ConfigArray` помечена
устаревшей, нужен переход на `defineConfig` из `eslint/config` (ESLint
core, а не `typescript-eslint`) — `web/eslint.config.js`.
- [ ] удалить мёртвые `tools.*.params` из root i18n после проверки потребителей;
до этого действует pattern-based policy-исключение
(`web/eslint-plugins/README.md`, раздел `dict-consistency`)
- [ ] e2e: `i18n.spec.ts` и `text-and-verdicts.spec.ts` дублируют локаторы из
`helpers/page.ts` вместо вызова — правило «спека зовёт helpers»
(`docs/testing-strategy.md`, раздел 5)
- [ ] Пересмотреть тесты — убрать точные совпадения текстов и любые селекторы,
привязанные к разметке или svelte-классам (сейчас остались:
`tool-flows.spec.ts`, `schema-tool-strings.test.ts`)
- [ ] можно ли в тестах получать i18n ключ вместо текста? можно ли написать lint
правило такое (запретить toContain без i18n)
- [ ] посмотреть ошибки e2e, разрешить запускать е2е без ручного подтверждения,
и рассмотреть - может уже пора включить их в ci\cd гейт
## Pipeline
- [ ] названия инструментов — в pipeline инструмент называется «обрезать png»,
но он работает с любыми картинками, наверное надо убрать; в заголовке
страницы — возможно, надо указать все форматы (связано с SEO)
- [ ] кнопка «добавить инструмент» в pipeline — обдумать селектор с нормальным
поиском, фильтром возможных инструментов и т.д.
- [ ] посмотреть реализацию flip animation svelte для анимации переключения
режима aligned\normal
- [ ] переделать визуал toggle компонента (которым режим переключается)
- [ ] **Идея 4. Batch-обработка архивов выбранным chain** — оценка L. Fan-out и
мультивыбор уже есть (идея 15: `web/src/lib/run-chain.ts`, zip-выгрузка
набора). Осталось: zip на вход (распаковка в браузере, порядок файлов,
поведение many → 1 → many), прогресс и отмена пофайлово, запуск по
сохранённой цепочке из `/chains`.
- [ ] **Идея 15. Остатки fan-out** — сделано: 1 → many не терминален,
мультизагрузка, склейка имён, per-file ошибки с warning. Отложено:
parts-grid на промежуточных тайлах (сейчас первая картинка набора),
прогресс/отмена, analyze-шаги пофайлово (сейчас firstOnly-warning).
## Инструменты
- [ ] split-to-parts, загружаем картинку, после этого переключаемся на режим by
tile - интерфейс начинает тормозить. уже пора переходить на worker\wasm?
- [ ] remove-alpha-channel - дубль инструмента с выбором цвета на замену, что с
такими делать вообще? оставить как seo? можно ли под капотом использовать
другой инструмент с хардкодед настройками?
- [ ] qr code to text, text to qr code
- [ ] bar code to text, text to bar code
- [ ] нужен инструмент для удаления фона по выбранной точке - удалять внутри
выделенной области
- [ ] сделать конвертацию в смайлики\награды для твитча (6 размеров или выбор
какой размер - 112\56\28px или 72\36\18)
- [ ] Font Style - обдумать выбор шрифта (google fonts???) как организовать
шрифты с кириллицей? сделать галочку "только с кириллицей"??? (решение о
наборе и лицензиях: `docs/plan-platform.md` §4 — только OFL/Apache с
паспортом, семейства с кириллицей)
- [ ] Свести convert-страницы (`convert-png-to-jpg`, `convert-png-to-webp`,
`png-to-bmp`) на один инструмент `convert` — зависит от S1f
(`docs/plan-seo.md` §4). Мешает не только `quality` (он живёт в схеме
инструмента), а сама модель: `output` с mime/ext — свойство `Tool`, а
`PageStep` умеет только `{ id, params? }`, поэтому страницы на общий `id`
получат одинаковый формат вывода. Нужно научить шаг переопределять формат
вывода
- [ ] **Идея 6. Конвертация формата — НЕ отдельный инструмент, а выбор в кнопке
Download** — оценка M/L. Решение и продуктовое обоснование:
`docs/plan-seo.md` §0 и задача **S1f**; почему селектор не заменяет
существующие convert-страницы — `docs/plan-seo.md` §5. Селектор формата и
качества в Download уже есть; «сжатие до целевого КБ» реализовано
(`fitWithinBytes` в `web/src/lib/core/io.ts`: бинарный поиск по quality
для lossy, по k квантования для PNG; для BMP — предупреждение, что лимит
не применим). Что осталось: нужна ли отдельная страница под интент «сжать
до N КБ» — открытый вопрос с вордстатом, имя не выбрано
(`docs/plan-seo.md` §5). Проработать вместе с достройкой download-флоу.
- [ ] **S1g под вопросом** — исходная формулировка (`docs/plan-seo.md` §4): на
convert-страницах блокировать в меню Download формат исходника, чтобы
`convert-png-to-jpg` не сохранял в png. Против: пользователь может
захотеть сохранить обработанный PNG или JPEG с другим качеством — блок
мешает легальному сценарию. Решение не принято; перед реализацией
переобдумать.
- [ ] **Лимит КБ: индикация активного сжатия** — сейчас заданный лимит никак не
виден, пока меню Download закрыто: пользователь может забыть про него и
случайно сжать следующие файлы. Нужен постоянный индикатор (значок/
подпись на кнопке или рядом). Связанный вопрос персистентности: лимит —
`$state` в `SchemaToolView.svelte`, при переходе на другой инструмент
сбрасывается в `init()` и в localStorage не пишется (в отличие от шагов
цепочки). Это безопасное поведение по умолчанию, но стоит осознанно
решить: оставить сброс при смене страницы или сохранять лимит (per-tool?
глобально?) вместе с цепочкой.
- [ ] **Лимит КБ/качество: превью итогового результата** — обдумать UI/UX: при
сжатии по размеру или низкому качеству дать возможность посмотреть
итоговый файл до скачивания — при сильном сжатии (низкий quality, грубое
квантование в PNG) искажения могут быть настолько заметны, что
пользователь откажется от варианта и выберет другой формат/лимит. Сейчас
превью показывает результат инструмента до re-encode, а сжатая версия
существует только внутри `fitWithinBytes`/`encode` в момент скачивания.
Открытые вопросы: превью на лету (дорого — encode на каждый ввод) или по
кнопке «предпросмотр»; где показывать (оверлей/замена тайла результата);
связь с идеей 14 (отображение маски) и пунктом про зум превью выше.
- [ ] **Идея 7. Страница `watermark-image-png` (водяной знак картинкой)** —
оценка M. Нужна overlay-механика: второй источник изображения
(getOverlay/store), параметры scale/opacity/position/margin/aspect.
Решается вместе с вопросом, как второй источник картинки вписывается в
schema-driven preview (`SchemaToolView`).
- [ ] **Идея 8. `png-info` (детальная информация о PNG)** — оценка M/L.
Отдельный райз: exif-теги, редактирование, структурированный вывод; нужен
свой отдельный случай в UI, не «ещё один text/verdict». Возможно нужна
вообще отдельная страница, несовместимая с другими инструментами: 1) она
работает не с изображением, а с метаданными из файла, 2) она не может быть
частью цепочки, т.к. результат не является изображением, 3) если надо
изменить теги, никакого форматирования и изменения в изображение вносить
не надо, только в метаинформацию.
- [ ] **Идея 9. Region-инструменты** (censor/erase/pixelate-area/blur-area/
sharpen-area/reverse-area) — ждут UI выделения области на превью. Вне
очереди.
- [ ] **Идея 10. Мультифайловые инструменты-потребители** (gif-to-frames,
separate-colors) — механизм «результат = набор файлов» (1 → many) уже есть
(`docs/architecture.md`, раздел 7), первый потребитель —
`split-into-parts-png`. Остальные подключаются по мере нужды.
- [ ] **Идея 11. Анимационные** (slow-reveal/fade/scrolling) — выход не PNG;
отдельное решение о формате.
- [ ] **Идея 12. HARD-серия** (glitch, barcode, signature-extract,
handwritten-digital).
## UI и качество
- [ ] **обдумать агрегацию предупреждений на тайле** — сейчас разрешено два
бейджа рядом (derived `resultNote` + runtime-warnings); после
использования решить, нужен ли один сводный бейдж со счётчиком и списком
- [ ] **лимит КБ/качество как авто-шаг пайплайна** — вынести size limit/quality
из меню Download в автоматический инструмент цепочки, который применяет
выбранные настройки (сжатие видно в превью и в цепочке, ошибки
недостижимости ложатся на тайл шага). Нужен флоу передачи индикатора из
такого шага в кнопку Download (ошибка/предупреждение/итоговый размер).
Связано с пунктами про индикацию активного сжатия и превью итогового
результата
- [ ] кнопку редактирования названия пайплайна на этой же странице
- [ ] при загрузке нескольких файлов, показывает source не той же высоты, как
result
- [ ] split to parts - посмотреть вариант с toggle component - может будет
удобнее чем sectioned buttons
- [ ] чип «Маска» (`resultCard.maskToggle` на тайлах результата) — попробовать
заменить на Toggle-компонент, когда тот будет доделан (см. пункт про
визуал toggle в «Pipeline»): возможно, будет удобнее и понятнее
- [ ] маска подгружается с задержкой при нажатии на чип «Маска» — сейчас
`runMask` считается только для включённых шагов (эффект в
`SchemaToolView.svelte`). Альтернатива: считать маску всегда вместе с
результатом, по нажатию просто показывать другую картинку. Оценить
достоинства/недостатки: отклик мгновенный, но лишний проход по пикселям на
каждый ран каждого шага с `runMask` (на больших изображениях — заметная
цена за функцию, которую могут не открыть)
- [ ] неудобно настраивать ползунками, некоторые инструменты удобнее настроить
через drag-n-drop. звучит сложно, но надо придумать процесс
- [ ] fav: текущий ui слишком дерганный — при клике на звёздочку элементы
мгновенно пересортировываются и под мышкой оказывается другой элемент.
Нужна или анимация, или механизм отложенного обновления позиций
- [ ] просмотр картинки в оригинальном размере, и возможно с зумом отдельных
областей, чтобы просмотреть мелкие артефакты, выбор разных подложек -
черная\белая\цветные\серая для проверки прозрачных картинок
- [ ] обдумать объединение пар `inputMode + source` и `resultKind + result` в
единую структуру, позволит упростить некоторые вещи - например
`sourceValue` \ `resultValue` в `SchemaPreview.svelte`
- [ ] Рассмотреть необходимость всех этих пропсов в `SchemaPreview.svelte` они
дублируют друг друга `ontextsource`, `onrendertext`, `oncopytext`,
`ondownloadtxt`, `ondownload`,
- [ ] resize keep aspect - работает, но немного не очевидное поведение при
прямоугольной картинке и выборе размера через быстрые кнопки (например
256х256). Воспроизведение поведения: keep aspect включено, загружаем
прямоугольную картинку 832 × 1232, картинка рескейлится до 173 × 256,
выключаем keep aspect, картинка рескейлится до 256 × 256 (с искажением
пропорций), включаем keep aspect - картинка рескейлится до размера 256 ×
379
- [ ] Переделать внешний вид инструментов без настроек, например Remove alpha
channel PNG "remove-alpha-channel-png". Сейчас выглядит слишком пустым.
- [ ] Пересмотреть поля - Plate, Position, Font Style - сейчас второй label
- [ ] поле ввода текста - сделать по умолчанию нормального размера, а не одну
строку для svg - форматирование или подсветку синтаксиса??? для bin\hex -
форматирование по колонкам??? для hex\bytes\rgba - пример в placeholder
- [ ] прикрутить кастомный color picker, добавить прозрачность (range?)
- [ ] обновить страницу kit или сделать storybook
- [ ] **проверить `cachedDataUrl` (WeakMap-кэш превью) в реальной работе** — GC
срабатывает недетерминированно, поэтому освобождение base64-строк (≈1.3×
бинарного размера картинки на каждый тайл) не гарантировано своевременно.
Проверить на длинной сессии с большими картинками (несколько ранов подряд,
смена инструментов): растёт ли heap в DevTools → Memory после повторных
ранов и уходит ли после принудительной сборки. Если записи копятся —
заменить на ограниченный LRU или явную инвалидацию при
`resetForHost`/новом ране (`web/src/lib/core/io.ts`, `cachedDataUrl`)
- [ ] `PreviewTile`: высота плитки задана только `min-height: clamp(...)`,
поэтому она не следует за пропорциями результата — широкий результат
уезжает в узкую полосу, а высокий упирается в `max-height: 100vh`. Нужно,
чтобы соотношение сторон выбиралось по результату в диапазоне 16:9…9:16
(`web/src/lib/components/schema/PreviewTile.svelte`).
- [ ] Радиусы бордеров: `--radius-m` ненулевой и применён ко всем бордерам
(`app.css`, `SchemaToolView.svelte`). Решить, где скругления реально есть
в дизайне, а где должен быть 0
- [ ] Component-тесты `SchemaToolView`/`SchemaPreview` требуют отдельного
решения: node Vitest не имеет DOM/canvas, а e2e уже покрывает поведение.
- [ ] **Идея 13. Контраст текста на акцентных кнопках — частично закрыт**. Тона
`--color-main`/`--color-accent` подняты под текущий порог
`palette.test.ts`; targeted-тест проходит. Light-тема всё ещё ниже AA 4.5
для обычного текста, а `--color-danger` в light-теме на границе: после
завершения редизайна вернуть порог 4.5 и перепроверить оба токена.
- [ ] **Идея 16. Главная должна отличаться от каталога** — оценка S. Сейчас
`src/routes/+page.svelte` и `src/routes/list-tools/+page.svelte` побайтово
идентичны (совпадают script, шаблон и стили), при этом `/list-tools` —
рабочий маршрут: на него ссылается крошка в `+layout.svelte` и он открыт
e2e-сценариями `catalog.spec.ts`, `i18n.spec.ts`, `navigation.spec.ts`.
Замысел: главная — крупнее и с более простым поиском, без категорий;
каталог остаётся группировкой с фильтрами. Детектор дублирования разметки
сознательно не вводим — `docs/decisions.md`, раздел 1, поэтому расхождение
ловится на ревью.
## SEO/GEO
- [ ] переименование бренда + домен: чек-лист в локальном файле
`plan-domain.local.md` (в git не входит, в клоне отсутствует; подробности
и порядок — `docs/plan-seo.md` §6, R1/R2)
- [ ] снять `noindex` со страниц инструментов, когда будут sitemap, canonical и
контент (S1h; блокирует индексацию всего сайта) — `docs/plan-seo.md` §4
- [ ] форматные страницы по конкурентным слагам (`crop-jpeg`, …) — только по
вордстату с уникальным контентом; редиректы только для опечаток и
переименований уже опубликованных страниц; клонов с canonical не делать
(`docs/plan-seo.md` §5)
- [ ] sitemap.xml из реестра + `Sitemap:` в robots.txt (S1b/S1c)
- [ ] Seo.svelte: per-tool OG-картинки (S1e) — у каждой страницы инструмента
своя превью-карточка 1200×630 для соцсетей/мессенджеров: имя инструмента,
бренд, иконка. Сейчас все страницы ссылаются на общую
`static/og/default.png` (генерирует `pnpm --dir web gen:og` —
Playwright-скриншот HTML-карточки в `web/scripts/gen-og.mjs`). Что делать:
расширить gen-og.mjs — проход по реестру страниц, карточка с названием
инструмента в `static/og/[slug].png`, в `Seo.svelte` подставлять og-URL по
slug страницы. Критерий приёмки: у `/tools/flip-png` в og:image своя
картинка с названием инструмента, файл лежит в `static/og/`
- [ ] контент страницы инструмента: seo-блок в словарях, how-to/FAQ/related (S2)
- [ ] JSON-LD (SoftwareApplication/FAQPage/Breadcrumb) + llms.txt (S3)
- [ ] дистрибуция: закрепить репо, alternative.to, Product Hunt, Reddit/HN (S4c)
- [ ] GSC: подключить домен, отправить sitemap, мониторинг индексации (S4a)
- [ ] GA4: cookieless-конфигурация, отключить рекламные audiences и signals,
`anonymize_ip` — сейчас в `web/src/routes/+layout.svelte` голый
`gtag('config')` (S4b)
## Платформа (API/PWA)
- [ ] Vercel: переезд хостинга с GitHub Pages + глобальная статистика
популярности инструментов через Vercel KV (serverless-функция: INCR при
открытии инструмента, чтение топа для скоринга поиска).
- [ ] PWA: manifest + service worker, оффлайн-режим, установка (после S1)
- [ ] API: спайк серверного ядра (нативный Rust vs edge-wasm), ключи, free tier
(после wasm-фаз 5–7)
- [ ] Шрифты: лицензирование (F1–F4) и DOM-free рендер (F5–F6) — до фазы 8
(`docs/plan-platform.md` §4)
## Переезд
- [ ] множественные числа (часть/части/частей; «N параметров», счётчики) —
функция `tPlural(path, n)` и форма `PluralForms` (обязательное `other`,
опциональные `one`/`few`/`many`); первые потребители — `part`/`parts` в
подписи результата и счётчики параметров. **Критерий приёмки:** у ключа с
plurals есть все формы, для которых нужен перевод, `other` никогда не
пустой, число подставляется в текст без склейки