/docx-from-sample - новый документ в оформлении образца
Берет готовый DOCX как источник оформления и собирает новый документ с тем же видом, но с другим содержанием. Оформление не воспроизводится вручную, а наследуется: образец открывается как документ, его тело очищается, а стили, нумерация, темы и параметры страницы остаются родными.
Когда применять
- "сделай такой же документ, но по другой теме", "в формате как в примере"
- заказчик прислал образец отчета, ТЗ, ПМИ, регламента - нужен свой документ в том же виде
- документов несколько и они должны выглядеть одинаково
- документ уже сделан, но оформление не совпадает с эталоном - пересобрать
Не для этого скила: правка существующего документа без смены оформления (штатные средства работы с DOCX),
markdown в DOCX без образца (скил md-to-docx), таблицы и презентации (xlsx, pptx).
Зависимости
python -m pip install python-docx pymupdf
pymupdf нужен для картинок страниц, Word - для сборки оглавления и экспорта в PDF
(на Windows через COM). Без Word документ соберется, но оглавление останется незаполненным.
Образец не зашит в скил
Скил глобальный и не привязан ни к одному шаблону. Образец задается профилем: ключ
sample в JSON либо флаг --sample при запуске. Для каждого нового шаблона делается
свой профиль, старые не трогаются.
| Ситуация | Что делать |
|---|---|
| Первый документ по этому шаблону | inspect_sample.py на образце, довести профиль, собрать |
| Еще один документ по тому же шаблону | взять готовый профиль, поменять только материал |
| Другой заказчик, другой бланк | новый профиль на новый образец |
| Профиль есть, образец переехал | --sample с новым путем либо поправить sample в профиле |
Путь к образцу может быть относительным: он ищется рядом с профилем, потом в текущей папке. Так профиль и образец переносятся между машинами вместе.
Где хранить профили - profiles/README.md. Коротко: профиль конкретного проекта живет
рядом с документами проекта или в ~/.claude/plans/<проект>/, а профиль шаблона, нужного
из разных проектов, кладется в profiles/ внутри скила.
Порядок работы
1. Снять оформление с образца
python scripts/inspect_sample.py "образец.docx" --json profile.json
Печатает секции с ориентацией и колонтитулами, реально используемые стили абзацев с примерами текста, разбор каждой таблицы (стиль, ширины, заливка шапки, границы, повтор шапки, стили абзацев в ячейках) и порядок блоков документа. Заодно пишет черновой профиль сборки.
Читать отчет ОБЯЗАТЕЛЬНО: черновой профиль угадывает уровни заголовков по кеглю, и это часто неверно. Сверить с отчетом: какой стиль стоит на разделах верхнего уровня, какой на подразделах, чем размечены подзаголовки внутри разделов.
2. Довести профиль
Профиль - это карта "роль в документе -> оформление образца". Формат и все ключи:
references/profile-format.md. Минимум, что правится руками:
styles.h1/h2/h3- уровни заголовков (из отчета, а не из догадки скрипта);tables.default_style_idиgrid_style_id- идентификаторы стилей таблиц;headings_map- какие тексты являются заголовками какого уровня в НОВОМ документе;footer.template- текст подвала,{title}подставляется.
Идентификаторы стилей таблиц берутся из отчета как есть. Обращение по идентификатору, а не по имени: имена стилей содержат символы, которые ломаются при копировании.
3. Подготовить содержание
Два пути.
Markdown - когда документ линейный (заголовки, абзацы, таблицы). Материал пишется
в .md, таблицы обычным markdown, секции переключаются маркерами <!-- landscape -->
и <!-- portrait -->. Сборка:
python scripts/md_to_docx_sample.py "материал.md" --profile profile.json --out "новый.docx" --title "Название" --author "Имя Ф."
Свой сценарий на python - когда документов несколько и они собираются из данных
(словарь, таблица, выгрузка). Тогда данные и сборка разделяются: модуль с данными плюс
вызовы SampleDoc. Так шесть однотипных документов правятся в одном месте и не
разъезжаются. Пример: references/build-example.py.
4. Проверить
python scripts/verify_result.py "новый.docx" --md "материал.md" --update-fields --png 1,2,9
Скрипт сверяет число таблиц и строк с исходником (ловит потерю строк и склейку таблиц), показывает секции и полосу набора, ищет таблицы шире полосы, считает шапки с заливкой и повтором, обновляет поле оглавления через Word и рендерит указанные страницы в PNG.
Картинки страниц надо посмотреть глазами. Ни один структурный тест не покажет разъехавшуюся верстку: заголовок внизу страницы отдельно от своей таблицы, текст, рвущийся по буквам в узкой колонке, пропавший колонтитул. Открыть PNG инструментом Read и сравнить с таким же рендером образца.
Рендер образца для сравнения:
python scripts/verify_result.py "образец.docx" --png 1,2,9 --outdir preview_sample
Что переносится из образца
| Элемент | Как |
|---|---|
| Стили абзацев и знаков, темы, шрифты | наследуются вместе с файлом образца |
| Автонумерация заголовков (1., 1.1., 1.1.1.) | из стиля образца; снимается точечно там, где номер не нужен |
| Стили таблиц | по идентификатору стиля из образца |
| Ширины столбцов | из профиля явно либо по содержимому: колонка-счетчик узкая, остальные делят полосу |
| Заливка шапки, границы, повтор шапки при переносе | из профиля, значения снимаются с образца |
| Колонтитулы | собираются заново по шаблону из профиля |
| Книжные и альбомные секции, поля | из профиля |
Колонтитулы и оглавление сознательно НЕ копируются из образца: в них почти всегда остается название чужого документа. Подвал собирается по шаблону с подстановкой названия.
Обязательные проверки перед сдачей
- число таблиц и строк совпадает с исходником;
- ни одна таблица не шире полосы набора;
- в каждой секции есть подвал (кроме титульной, если так в образце);
- стили в документе те же, что в образце (скрипт покажет чужие);
- поле оглавления собрано, а не оставлено заглушкой;
- страницы просмотрены глазами хотя бы выборочно: титул, первая страница с таблицей, страница с переносом таблицы через страницу.
Грабли
Полный разбор с симптомами: references/ooxml-pitfalls.md. Коротко, самое дорогое:
- Две таблицы подряд склеиваются в одну. Между таблицами обязателен пустой абзац, иначе Word объединит их, и число таблиц молча уменьшится.
- Подвал пропадает на первой странице каждой секции. Свойство "первая страница отдельно" наследуется новой секцией от предыдущей, его надо сбрасывать.
- Ориентация. В python-docx смена ориентации не меняет ширину и высоту страницы,
их надо менять самому. В javascript-библиотеке
docxнаоборот: она меняет их сама, и ручная перестановка дает двойной переворот. - Заливка шапки не появляется сама даже когда стиль таблицы ее рисует: в образцах она обычно задана явно на ячейках. Ставить явно.
- Узкая колонка-счетчик рвет свой заголовок по буквам. Ширина такой колонки должна считаться по длине заголовка: "№ п/п" уже, чем "Номер версии".
- Строки-разделители таблицы ("От Заказчика" на всю ширину) в markdown выглядят как повтор текста по всем колонкам - в DOCX их надо объединять в одну ячейку.
Ограничения
- Скил не переносит картинки, диаграммы и фигуры из образца - только текстовое оформление.
- Профиль под жанр документа делается один раз и потом переиспользуется; на новый жанр нужен новый профиль.
- Автоопределение уровней заголовков в черновом профиле - подсказка, а не результат.
- Сборка оглавления и экспорт в PDF требуют установленного Word.