Files
easy-png-tools2/docs/backlog.md
T

26 KiB
Raw Blame History

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) — оценка труда, не приоритет.

Pipeline

  • названия инструментов — в pipeline инструмент называется «обрезать png», но он работает с любыми картинками, наверное надо убрать; в заголовке страницы — возможно, надо указать все форматы (связано с SEO)
  • кнопка «добавить инструмент» в pipeline — обдумать селектор с нормальным поиском, фильтром возможных инструментов и т.д.
  • посмотреть реализацию flip animation svelte для анимации переключения режима aligned\normal
  • переделать визуал toggle компонента (которым режим переключается)
  • Идея 1. Заменить инструмент шага без удаления — оценка M. В заголовке карточки шага кнопка «поменять инструмент»: заменяет инструмент на месте (любой шаг, не только первый), остальные шаги и их параметры сохраняются, вход перечитывается. Открытый вопрос: что делать с несовместимыми входами (text-source ↔ file).
  • Идея 3. Несколько цепочек: сохранение и загрузка — оценка M. Именованные цепочки в localStorage (список, создать/переименовать/ удалить), быстрое переключение. Формат экспортного JSON расширить опциональным полем имени; обратной совместимости со старыми выгрузками не делаем — формат не устоялся: он появится вместе с фазой 11 docs/roadmap.md и до её старта может измениться. Плюс отдельная страница со списком всех цепочек: удалить, переименовать, добавить новую, «использовать» (переход на страницу инструмента с этой цепочкой). На странице — упрощённый вид: только список инструментов цепочки, без реального выполнения и параметров.
  • Идея 4. Batch-обработка архивов выбранным chain — оценка L. Вход — zip-архив картинок (распаковка в браузере), прогон текущего или выбранного сохранённого chain по каждому файлу, сборка результата обратно в zip для скачивания. Зависит от идеи 3 (выбор цепочки) и от экспортного формата pipeline JSON; прогресс и ошибки — пофайлово.
  • Идея 15. Набор файлов в пайплайне: 1 → many не должен быть терминальным — оценка L. Сейчас execute принимает один source: PixelImage | undefined и возвращает один ToolResult, а SchemaToolView раскладывает вывод в result / fileResult / textResult по resultKind — поэтому шаг с result: "files" упирается в конец цепочки. Направление: следующий инструмент применяется ко всем картинкам предыдущего результата (fan-out), а many → 1 (вход = архив или несколько файлов) — обратная сторона того же контракта. Терминальными остаются только результаты, которые не картинка (text, verdict). Что обдумать: - где проходит граница: один вызов run(ctx) на файл (имя части склеивается в FileResult.files) или батч целиком на стороне исполнителя; executor/protocol.ts files уже сериализуются, но при батче нужен прогресс и отмена; - частичные ошибки: один битый файл не должен ронять весь шаг — нужен per-file отчёт, а не один ToolError на шаг; - имена частей на каждом шаге и Download для набора (сейчас zip по page.slug, SchemaToolView.download()); - обратная сторона: распаковка zip в браузере, порядок файлов, поведение many → 1 → many в одной цепочке. Зависит от идеи 10 (остальные потребители 1 → many) и идеи 4 (batch по архиву), docs/roadmap.md фаза 8 «batch-страница».

Инструменты

  • 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)
  • сделать несколько проходное сжатие png для получения необходимого размера файлов, посмотреть реализацию в twitch-emote-resizer
  • 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. Механическая часть уже есть: Tool.output (OutputFormat: mime/ext/qualityParamId) и кодирование по нему в SchemaToolView.download() — docs/architecture.md, раздел 3. Что осталось сверх S1f: - экспорт с лимитом размера → «сжатие до целевого КБ»: для lossy это quality в селекторе формата, для PNG — бинарный поиск по k из квантования. Нужна ли отдельная страница под этот интент — открытый вопрос с вордстатом, имя не выбрано (docs/plan-seo.md §5). Проработать вместе с достройкой download-флоу.
  • Идея 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).
  • Идея 14. Отображение маски для инструментов (runMask) — придумать и реализовать процесс показа маски результата. Контекст: удалённый UI-v1 умел показывать ч/б превью-маску «что будет вырезано» отдельным полем; при переходе на единый run(ctx) этого поля не осталось — executor и schema-превью зовут run() напрямую, маска не возвращается. Идея 1: дать каждому run возможность вернуть (или инструмент — объявить) runMask — ч/б изображение маски изменений либо иной подход (отдельное поле mask + функция маски, второй результат, overlay). Оценка — на усмотрение при проработке (S/M). Пока живём без неё. Идея 2: каждый run возвращает два изображения — для отображения (показывает маску или сам результат) и для передачи в следующий инструмент (всегда результат). Оценка — на усмотрение при проработке (S/M). Пока живём без неё. Первые кандидаты на маску: remove-color-from-png, remove-background-png.

UI и качество

  • split to parts - посмотреть вариант с toggle component - может будет удобнее чем sectioned buttons
  • неудобно настраивать ползунками, некоторые инструменты удобнее настроить через 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
  • 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, поэтому расхождение ловится на ревью.

Тесты и lint

  • 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)
  • чистка под новые конвенции комментариев и тестов: правила conventions/ascii-only (тесты — ASCII), conventions/comments-english (комментарии — английский), conventions/comment-format (≤5 строк на блок, ≤15% файла) уже работают в warn-режиме, но в lint:all отключены через override в web/scripts/lint-all.mjs (baseline ≠ 0). Критерий закрытия: ноль срабатываний по всем трём правилам, overrides удалены, правила переведены с warn на error
  • убрать в тестах все нестандартные символы →, длинные тире, русский язык и т.д. — часть чистки под conventions/ascii-only (см. выше)
  • комментарии на английском — часть чистки под conventions/comments-english (см. выше)

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 никогда не пустой, число подставляется в текст без склейки