diff --git a/docs/specs/482-pdf-export-polish.md b/docs/specs/482-pdf-export-polish.md new file mode 100644 index 00000000..28628a6c --- /dev/null +++ b/docs/specs/482-pdf-export-polish.md @@ -0,0 +1,474 @@ +# #482 — Доводка экспорта пространства в PDF + +- **Issue:** https://github.com/Matysh/houseplan-card/issues/482 +- **Тип / приоритет:** bug + polish / P1 +- **Трек:** полный; меняются геометрия размеров, PDF-примитивы, компоновка + страницы, адаптивность View-диалога и golden-эталон +- **Оценка:** пользовательская ценность 8/10; ценность для разработки 7/10; + сложность 7/10; риск 7/10 +- **Связано:** #52, #53; `docs/specs/052-view-dimensions.md`, + `docs/specs/053-pdf-export.md`, `docs/PDF-EXPORT.md`, + `docs/TOUCH-SUPPORT.md` + +## 1. Сценарий + +Персона — Home admin из `docs/SCOPE.md`. Поверхность — полная карточка House +Plan в режиме View на desktop либо touch-устройстве. Момент — пользователь +открывает «Сохранение в PDF», выбирает состав архитектурного чертежа и сохраняет +текущее пространство для печати, передачи строителю или обсуждения планировки. + +В исходном плане могут одновременно присутствовать внешние и внутренние стены, +проёмы, перегородки, колонны, ступенчатые и вогнутые комнаты, декор, растровая +подложка и заданное направление севера. + +## 2. Что человек увидит до и после + +**До:** узкий диалог может получить горизонтальный scroll; противоположные +стороны дублируют одинаковые размеры; почти совпадающие вершины иногда создают +ложную диагональ; подписи прилипают к стенам; стены не похожи на стены плана; +чертёж плохо заполняет лист; север показан упрощённой стрелкой; внизу печатается +техническая легенда `wall · door · window`. + +**После:** диалог помещается от 320 CSS px, размерные цепочки остаются только у +реальных осевых граней и не повторяют локальную противоположную пару, подписи +расположены равномерно и не пересекают стены, физические стены имеют фон +`#7f7f7f` и штриховку, полный чертёж оптимально вписан и центрирован, север +обозначен векторным компасом, а технической легенды нет. + +## 3. Подтверждённые причины + +1. `compactRing()` удаляет коллинеарные точки до схлопывания соседних точных и + почти точных дублей. В ступенчатом контуре это соединяет несмежные стороны + хордой. На приложенном примере ложные `3.39 m` и `3.93 m` совпадают с + диагоналями между реальными ортогональными участками; стены под углом 72° в + исходном плане нет. +2. Размеры формируются для каждой пригодной стороны независимо: понятия + локальной пары противоположных граней нет. +3. Внутренние подписи используют фиксированные 2 mm без учёта bbox текста и + тела стены; fallback сдвигает только текст вдоль стены. Внешняя shelf также + может двигаться отдельно от своей размерной линии. +4. Ориентация выбирается по сырому bbox архитектуры, до построения размеров и + выносок. Дополнительно всегда резервируются приближённые 30/48 mm, после чего + центрируется только архитектура. Поэтому масштаб и свободные поля не + соответствуют фактической печатной сцене. +5. PDF writer умеет заливать и обводить path, но не умеет even-odd clipping для + штриховки и заполненный составной vector path для нового компаса. +6. Общий двухзнаковый formatter PDF превратит `127 / 255` в `0.5`, то есть в + `#808080`. Для точного `#7f7f7f` цвету нужна отдельная точность. +7. В CSS диалога padding прибавляется к `min-width`, flex-подписи не могут + сжиматься, а footer запрещает перенос. + +## 4. Изменяемый контракт + +Это ТЗ заменяет только противоречащие ему части #53: + +- §7.1: цвет и вид физических стен; +- §7.3: правило «все четыре стороны» и размещение размеров; +- §7.5: упрощённую стрелку севера и архитектурную легенду; +- §8.1–8.2: выбор ориентации, масштаба и центрирование; +- связанные AC4, AC6 и golden-ожидания. + +Остальные гарантии #53 сохраняются: один лист A4, стандартный масштаб, +генерация на клиенте, Unicode-шрифт, детерминированные байты, отсутствие +маркеров и live-state, опциональные названия/размеры/декор/подложка и ленивый +PDF chunk. + +## 5. Скоуп + +1. Сделать диалог PDF безопасным на узкой View-поверхности. +2. Исправить нормализацию контуров до генерации размеров. +3. Ограничить размеры горизонтальными и вертикальными гранями с каноническим + near-axis допуском. +4. Убирать только одну из локальной пары геометрически противоположных равных + граней. +5. Перестроить размещение внутренних и внешних размеров в согласованные полосы. +6. Добавить физическим стенам, перегородкам и колоннам точный фон и штриховку с + clipping по их реальной геометрии и проёмам. +7. Выбирать ориентацию и стандартный масштаб по bbox фактически построенной + сцены и центрировать эту сцену в печатном поле. +8. Заменить стрелку севера на переданный векторный компас. +9. Удалить архитектурную легенду, сохранив дату, версию и масштабную линейку. +10. Обновить тесты, golden, документацию и лицензионное уведомление. + +## 6. Не входит + +- изменение модели пространства, wall segments, openings, decor или PDF + настроек в `localStorage`; +- новые настройки экспорта либо изменение значений существующих галочек; +- размеры диагональных стен, дуг, мебели, проёмов, перегородок или колонн; +- многостраничный PDF, другой формат бумаги или ручной выбор масштаба; +- ручное перетаскивание размеров и автоматические строительные размерные цепи; +- изменение вида стен на интерактивном плане; +- изменение семантики `north_deg` либо способа задания севера; +- печать устройств, их состояний или подключение внешних PDF-сервисов; +- общий рефакторинг writer за пределами нужных заполненных vector path, + clipping и точной сериализации цвета. + +Если исправление потребует нового config-поля, изменения пользовательских +галочек или поддержки размеров настоящих диагональных стен, задача возвращается +в `S3-spec`. + +## 7. Диалог на узкой поверхности + +- Поддерживаемая минимальная ширина viewport — 320 CSS px. +- Surface, body и footer используют `box-sizing:border-box`, `min-width:0` и не + шире доступной области. Padding входит в вычисленную ширину. +- Текст внутри label может переноситься; checkbox/radio/input не сжимается и не + отделяется от начала своей подписи. +- При ширине, на которой две footer-кнопки с локализованными подписями не + помещаются, footer становится одной колонкой: «Отмена» сверху, основное + действие «Сохранить PDF» снизу; обе кнопки занимают доступную ширину. +- На большей ширине сохраняется действующий горизонтальный footer. +- Горизонтальный scroll запрещён для документа, dialog surface, body и footer. + Вертикальный scroll допустим; все элементы остаются доступны. +- Интерактивные цели сохраняют минимум 44×44 CSS px, focus ring и существующий + keyboard contract. +- Контракт проверяется во всех четырёх локалях EN/RU/DE/FR, а не только на самой + короткой строке. + +## 8. Нормализация контуров и допустимые грани + +### 8.1 Порядок очистки ring + +Перед поиском коллинеарных вершин каждый конечный ring нормализуется так: + +1. удалить повтор последней точки, если он замыкает первую; +2. схлопнуть соседние точные либо близкие точки, включая пару на seam + «последняя → первая»; +3. только после этого итеративно удалять промежуточную точку действительно + прямого участка; +4. повторять шаги 2–3 до fixed point либо пока проход ничего не изменил. + +Близость точек — не более 1 mm в физических координатах плана, переведённых в +render coordinates через действующий `cell_cm`. Это только фильтр печатной +геометрии: исходный config не мутируется. Точки с нечисловыми координатами не +создают размер. + +Точка считается промежуточной только когда оба соседних вектора ненулевые, +коллинеарны в пределах канонического допуска и их скалярное произведение +положительно. Поэтому разворот, настоящий угол и короткая грань между разными +точками не превращаются в хорду. Результат не содержит нулевых рёбер. + +### 8.2 Только осевые размеры + +Размер допускается только для: + +- строго горизонтальной/вертикальной грани; либо +- near-axis грани, отклонённой не более чем на канонические 0.25° из + `src/near-axis.ts` (`NEAR_AXIS_MAX_DEGREES` / `NEAR_AXIS_MAX_SLOPE`). + +Для near-axis шума печатная размерная грань выравнивается по major axis через +её midpoint и использует длину major projection. Исходная геометрия не +изменяется. Грань за пределом допуска полностью исключается: запрещено строить +проекцию, хорду или соединять её соседние концы. + +Каждый кандидат сохраняет стабильную ссылку на исходные ring и edge index до +компактации. Стабильность нужна для дедупликации, layout и детерминированного +порядка, но не экспортируется в PDF. + +## 9. Локальная дедупликация противоположных размеров + +Равный отформатированный текст сам по себе никогда не является основанием для +удаления. Дедупликация выполняется отдельно: + +- внутри одного room inner contour; либо +- внутри одного связного external outer ring. + +Два кандидата образуют пару только если одновременно: + +1. они имеют одну ось и противоположные нормали; +2. их tangent projection intervals совпадают с допуском 1 mm; +3. их projected lengths совпадают с допуском 1 mm; +4. midpoint соединяющего их перпендикуляра лежит внутри соответствующего + простого ring; +5. обе грани остаются допустимыми после §8. + +Для external ring проверяется внутренняя область самого ring; внутренние holes +не связывают несвязанные здания. Один кандидат участвует максимум в одной паре. +Если возможны несколько пар, выбирается ближайшая по перпендикуляру, затем по +стабильному edge key. + +Из пары остаётся сторона с лучшим placement score: меньше hard collisions с +телом архитектуры/границей печатного поля/уже размещёнными более приоритетными +аннотациями, затем больше свободного пространства по нормали. Полная ничья +разрешается минимальным стабильным ключом `(axis, tangentStart, normalSign, +ringIndex, sourceEdgeIndex)`. + +Следствия: + +- прямоугольная комната получает один горизонтальный и один вертикальный + внутренний размер, а не четыре; +- одинаковые значения у разных комнат, разных connected rings либо на разных + осях сохраняются; +- равные, но не противоположные участки L/ступенчатого контура сохраняются; +- общий горизонтальный и вертикальный габарит одинаковой длины не конфликтуют. + +## 10. Размещение размеров + +Все вычисления clearance выполняются в mm страницы после выбора масштаба и по +фактическому rotated bbox текста. + +### 10.1 Общие правила + +- Центр текста проецируется в midpoint измеряемой грани. +- Между bbox текста и ближайшей гранью тела стены остаётся минимум 1 mm. +- Текст, основная размерная линия и shelf не пересекают тело стены. Extension + внешнего размера может начинаться на самой внешней грани стены, но не входит + внутрь её тела. +- Для вогнутого ring внутренняя/внешняя нормаль определяется пробами + point-in-ring по обе стороны грани, а не только направлением к centroid. +- Нельзя исправлять collision индивидуальным tangent-jitter текста. + +### 10.2 Внутренние размеры + +Внутренний размер сохраняет действующий лаконичный text-only вид. Его базовая +полоса находится внутрь комнаты на расстоянии, равном половине normal extent +текста плюс 1 mm от реальной внутренней грани стены. + +Размеры одного room contour с общей стороной/осью/нормалью относятся к одной +полосе. Если любой элемент полосы конфликтует с архитектурой либо уже принятым +более приоритетным элементом, вся полоса смещается внутрь шагами 3 mm до первого +валидного положения. Если валидного положения нет, сохраняется существующая +выноска для непрямоугольной комнаты; произвольный сдвиг текста вдоль стены не +допускается. + +### 10.3 Внешние размеры + +Базовая размерная линия проходит на 6 mm наружу от внешней грани тела стены. +Текст расположен снаружи линии с зазором 1 mm. Extension lines начинаются на +грани тела стены и заканчиваются на своей размерной линии. + +Коллинеарные внешние размеры с общей осью и внешней нормалью образуют одну +полосу. При collision вся полоса — line, extensions, shelf и text — смещается +наружу шагами 4 mm. Shelf используется только когда текст шире доступного +участка и остаётся частью той же полосы. + +Базовое расстояние одинаково для всех размеров своего класса. Дополнительные +полосы разрешены только как детерминированный ответ на collision; отдельная +подпись не может «прилипнуть» к стене или уехать независимо. + +## 11. Вид физических стен + +В PDF следующие объекты получают одинаковый material: + +- физические room/external/shared стены ненулевой толщины; +- перегородки ненулевой толщины; +- квадратные и круглые колонны ненулевого размера. + +Material состоит из: + +1. фон RGB `127 127 127`, то есть точный `#7f7f7f`; +2. одна семья диагональных линий 45° к странице, шаг 3 mm, толщина 0.18 mm, + цвет основной печатной краски; +3. существующий контур толщиной 0.25 mm поверх fill и hatch. + +Фаза штриховки привязана к началу страницы, поэтому соседние стены не начинают +узор заново и не дают заметных швов. Hatch строится в paper coordinates и +обрезается even-odd clip path (`W* n` или эквивалентом) фактического тела +каждого объекта. Проёмы остаются чистыми holes; hatch/fill не попадает в tunnel. + +Нулевая стена сохраняет действующий line contract и не получает ни серый фон, +ни hatch. Decor и растровая подложка не меняются. + +Цвет сериализуется отдельным formatter с достаточной точностью (минимум пять +знаков после точки для `127/255`). Координатный formatter writer не меняется: +это сохраняет детерминизм и размер файла. + +## 12. Компоновка листа + +### 12.1 Кандидаты + +Для обеих ориентаций A4 — portrait и landscape — строится фактическая сцена с: + +- архитектурой, включёнными decor/подложкой; +- реально оставшимися dimension lines, extensions, shelves и text; +- фактически понадобившимися выносками; +- line widths и rotated text bbox. + +Приближённые безусловные резервы 30/48 mm удаляются. Header и footer не входят +в plan scene и заранее вычитаются из доступного поля. + +Для каждой ориентации проверяется действующий стандартный ряд масштабов от +наиболее крупного к мелкому. Кандидат валиден, только если полный scene bbox с +допуском 0.5 mm находится внутри печатного поля. + +### 12.2 Выбор и центрирование + +Побеждает: + +1. минимальный denominator, то есть наиболее крупный стандартный масштаб; +2. при равном масштабе — большая доля площади печатного поля, занятая полным + scene bbox; +3. при полной ничьей — portrait. + +После выбора переводится весь scene целиком: paths, raster, размеры, текст и +выноски. Центр полного bbox совпадает с центром доступного plan field с допуском +0.5 mm. Ни один элемент не пересекает header/footer или поля страницы. + +Подпись масштаба и scale bar вычисляются из выбранного denominator; нельзя +визуально увеличить чертёж, оставив старое значение масштаба. + +## 13. Векторный компас + +Если у пространства задан `north_deg`, существующее место северного указателя +занимает `compass-line` из VMware Clarity Assets (`viewBox 0 0 36 36`) — обе +канонические filled path, без растрирования и без внешних ссылок. Источник: +https://github.com/vmware-archive/clarity-assets/blob/master/icons/travel/compass-line.svg. + +Переданный владельцем файл имеет SHA-256 +`461EBD20E65DF8F017CADCCFEF4F58E7A7E5CB3A8877B4797E6C81C011E41F0B` и +совпадает по path с каноническим ассетом. В репозитории сохраняются MIT license +и copyright VMware 2018 рядом с ассетом либо в third-party notices. + +Компас: + +- сохраняет квадратный aspect ratio и основной печатный цвет; +- остаётся vector content PDF; +- вращается по прежней семантике: `0°` — северная стрелка вверх страницы, + `90°` — вправо, `180°` — вниз, `270°` — влево; +- использует действующий resolver `north_deg` и подпись `pdf.north`; +- отсутствует, если направление севера не задано. + +PDF writer получает минимально необходимый filled vector primitive с явно +заданными fill rule/fill/stroke. Он не становится универсальным SVG renderer. + +## 14. Footer и i18n + +Архитектурная легенда полностью удаляется: в PDF нет `wall · door · window`, её +переводов либо разделителей. Неиспользуемые `pdf.legend.*` удаляются из EN/RU/ +DE/FR словарей. + +В footer сохраняются локализованная дата, `House Plan v…`, действующие +разделители и масштабная линейка. Новых пользовательских строк нет. Изменённые +описания в документации обновляются на EN/RU; существующие строки диалога +проверяются во всех четырёх локалях. + +## 15. Модель, совместимость и rollback + +Config schema, `config_version`, модель пространства и ключи сохранённых PDF +опций не меняются. Миграции и downgrade converter не нужны. Экспорт читает +исходную модель, создаёт нормализованную временную геометрию и не записывает её +обратно. + +Rollback — возврат frontend/PDF lazy chunk к предыдущей версии. Сохранённые +планы и пользовательские настройки остаются совместимы в обе стороны. + +## 16. Touch, доступность, безопасность и производительность + +- PDF-диалог относится к View, поэтому полностью поддерживается на touch, а не + по best-effort правилу редакторов. На 320 px он остаётся читаемым и usable. +- Клавиатура, Escape, focus trap, focus return и screen-reader names действуют + как в #53; перестройка footer не меняет DOM-порядок действий. +- Генерация остаётся полностью локальной. Новый ассет вендорится, runtime + network request, пользовательский HTML и новые данные HA не появляются. +- Lazy boundary сохраняется: до открытия экспорта PDF writer, compass и шрифт + не загружаются в initial bundle. +- Детерминированность байтов при одинаковых `now`, config и options сохраняется. +- Бюджет построения сцены из теста #53 остаётся `<200 ms` для его large-house + fixture на референсной Node-среде. Проверка двух ориентаций не должна + выполнять повторный разбор модели или декодирование растра. + +## 17. Acceptance criteria и доказательства + +| AC | Критерий | Обязательное доказательство | +|---|---|---| +| AC1 | При viewport 320×760 в EN/RU/DE/FR ни document, ни surface/body/footer диалога не имеют горизонтального overflow; кнопки полностью доступны и не меньше 44×44 px | targeted browser smoke с `scrollWidth <= clientWidth`, bbox кнопок и фактическим export | +| AC2 | Точные/почти точные соседние вершины схлопываются до удаления коллинеарных точек; каждый реальный поворот сохраняется; нулевых рёбер и ложных `3.39/3.93` нет | unit fixture регрессии + mutation witness, отключающий duplicate normalization | +| AC3 | Размер получают только H/V и near-axis ≤0.25°; грань за порогом не создаёт проекцию/хорду | boundary unit на обе стороны допуска + scene test + mutation witness без axis filter | +| AC4 | Удаляется одна локальная противоположная пара, но сохраняются одинаковые значения разных комнат/rings/осей и непарные равные грани L-контура | unit topology matrix + scene counts + mutation witness глобальной дедупликации | +| AC5 | Подпись центрирована, clearance ≥1 mm, базовая полоса едина; collision перемещает целиком полосу, включая line/extensions/shelf | unit bbox/concave tests + focused golden + mutation witness старого tangent-jitter | +| AC6 | Физические стены/перегородки/обе колонны имеют точный `#7f7f7f` и page-anchored hatch; openings чисты; zero wall не заштрихована | writer operators/color unit + PDF raster semantic probes/golden + mutation witness без even-odd clip | +| AC7 | Обе A4 orientation оцениваются по полному фактическому bbox; выбран максимальный стандартный масштаб, сцена целиком внутри поля и центрирована ≤0.5 mm | scene unit с portrait/landscape и реальными callouts + focused golden + mutation witness старого raw-aspect выбора | +| AC8 | Компас содержит обе канонические path, остаётся vector и верно ориентирован при 0/90/180/270°; без north отсутствует; license сохранена | parser/unit + writer PDF parse + raster probes + license check + mutation witness старой стрелки | +| AC9 | Архитектурная легенда и `pdf.legend.*` отсутствуют, дата/версия/масштаб сохраняются | extracted-text unit/smoke и i18n consistency + mutation witness возврата легенды | +| AC10 | Сохраняются один A4, стандартный scale, все четыре content-toggle, Unicode, отсутствие devices/live-state, deterministic bytes и lazy loading | актуализированные существующие unit/smoke тесты #53 | +| AC11 | Построение large-house scene укладывается в `<200 ms`; initial bundle не получает PDF-код | perf unit + bundle/lazy manifest check | +| AC12 | Пользовательская и техническая документация соответствует новому результату, а golden/docs fingerprints актуальны | `check-docs`, Linux golden verify и полный Linux docs artifact review | + +## 18. Тест-план + +### Unit / component + +- `pdf-dimensions`: exact/near duplicate, seam duplicate, turn retention, + fixed-point compact, zero edge, 0.25° boundary, true diagonal, rectangle pair, + L-contour false pair, equal dimensions across rooms/rings/axes. +- `pdf-scene`: retained counts, midpoint, clearance, whole-lane shift, concave + normal, exact full bbox, both orientations, scale bar, wall/partition/column + material, opening holes, zero wall, compass cardinals, footer text and perf. +- `pdf-writer`: high-precision color, filled compound vector, even-odd clip, + parseability and deterministic bytes after new operators. +- отдельный compass unit: обе path разбираются в конечные координаты, имеют + квадратный bbox и детерминированно трансформируются. + +### Browser smoke + +- текущий полный экспорт и отказ lazy chunk; +- 320×760 и четыре локали с измерением overflow; +- stacked footer сохраняет cancel/save behavior и download; +- извлечённый текст не содержит легенду. + +### Visual / golden + +Обновить `pdf-export-geometry-light` и добавить focused scenario с почти +квадратным планом, near-duplicate углом, локальной парой, одинаковыми размерами +двух комнат, проёмом, zero wall, перегородкой, обеими колоннами и `north_deg`. + +Semantic guard проверяет: + +- ненулевой architectural ink и минимальное заполнение plan field; +- серый участок стены с контрастными hatch-полосами; +- чистую область проёма; +- vector/raster ink в области компаса; +- отсутствие содержимого за полями и приблизительное центрирование. + +На Windows разрешены unit/typecheck/build/browser smoke и диагностический +`golden:verify`. Канонические golden и десять docs screenshots переснимаются в +Linux CI/закреплённом контейнере: DirectWrite не является принимаемой заменой +Linux FreeType. + +Backend и HA API не меняются, поэтому backend pytest не является целевым +доказательством этой задачи. + +## 19. Документация и release artifacts + +Обновить: + +- `docs/PDF-EXPORT.md` — размеры, hatch, layout, compass, отсутствие легенды; +- `docs/USER-GUIDE.md` и `docs/USER-GUIDE.ru.md` — вид результата; +- `docs/TESTING.md` — структурные и visual PDF gates; +- `docs/specs/053-pdf-export.md` — явные ссылки на заменённый контракт #482; +- `docs/specs/README.md`, `docs/STATUS.md`, `docs/ARCHITECTURE.md` при изменении + перечисленных модулей; +- screenshot диалога PDF и оба changelog. + +Коммиты реализации получают `User-Visible: yes`. Changelog EN/RU коротко +описывает исправленный экспорт и ссылается на #482. Release body по общему +процессу содержит только значимое пользовательское изменение и ссылки на оба +changelog. + +## 20. Ожидаемая карта изменений + +- `src/pdf/pdf-dimensions.ts` — нормализация, axis filter, кандидаты и пары; +- `src/pdf/pdf-scene.ts` — dimension lanes, material, full-scene candidates; +- `src/pdf/pdf-writer.ts` — clipping, filled vector и точный цвет; +- `src/pdf/pdf-compass.ts` и лицензионный notice — канонический compass asset; +- `src/pdf/hp-pdf-dialog.ts` — narrow responsive contract; +- `src/i18n/{en,ru,de,fr}.json` — удаление мёртвых legend keys; +- targeted unit/smoke, golden matrix/guards/fixtures и документы §19. + +Карта не является разрешением на сопутствующий refactoring. Любой новый +runtime dependency, config migration или выход за PDF/View dialog требует +возврата в `S3-spec`. + +## 21. Риски + +| Риск | Снижение | +|---|---| +| Локальная дедупликация удалит два разных размера с одинаковым числом | topology pair требует общий ring, ось, interval, противоположные normals и inside probe; negative matrix AC4 | +| Очистка дублей срежет настоящий короткий участок | физический epsilon 1 mm, forward-dot и сохранение каждого turn; boundary tests AC2 | +| Штриховка закроет проём либо даст швы | page-anchored pattern + even-odd clip + raster probes AC6 | +| `#7f7f7f` округлится до `#808080` | отдельный high-precision color formatter и operator/raster test | +| Более точный layout станет медленным | model parse/raster decode один раз, perf budget AC11 | +| Полный bbox всё ещё пропустит rotated text/line width | bbox строится после фактических annotations и включает stroke/text extents; adversarial tests AC7 | +| Compass нарушит лицензию или раздует runtime | две вендоренные path, MIT notice, без общего SVG runtime и в lazy chunk | +| Narrow fix сломает focus либо действия | DOM-order неизменен, browser keyboard/download smoke AC1/AC10 | diff --git a/docs/specs/README.md b/docs/specs/README.md index 57a45f9c..89774dc1 100644 --- a/docs/specs/README.md +++ b/docs/specs/README.md @@ -28,6 +28,7 @@ GitHub Issues и GitHub Projects (v2) остаются единственным | Issue | ТЗ | |---|---| +| [#482](https://github.com/Matysh/houseplan-card/issues/482) Доводка экспорта пространства в PDF | [482-pdf-export-polish.md](482-pdf-export-polish.md) | | [#471](https://github.com/Matysh/houseplan-card/issues/471) Убрать белые raised plates вокруг маркеров и названий комнат | [471-isometric-overlay-white-plates.md](471-isometric-overlay-white-plates.md) | | [#6](https://github.com/Matysh/houseplan-card/issues/6) Vacuum XCME path segments | [006-vacuum-xcme-path.md](006-vacuum-xcme-path.md) | | [#7](https://github.com/Matysh/houseplan-card/issues/7) Valetudo room outlines | [007-vacuum-valetudo-room-outlines.md](007-vacuum-valetudo-room-outlines.md) |