Files
Igor20264 510f7e7adf
Python application / build (push) Waiting to run
v0.5.2
Что то сделал
2026-09-08 19:37:54 +03:00

47 KiB
Raw Permalink Blame History

GhostEditor / md2gost — полное описание проекта

Версия пакета: 0.1.0. Python ≥ 3.10.
Репозиторий: конвертер учебных отчётов Markdown → DOCX по методичке РТУ МИРЭА (ГОСТ 7.32-2017) и профилям ПИС / АПИД. Рядом — два дополнительных пайплайна: FODT (LibreOffice) и LaTeX → PDF.

Этот файл — карта всего репозитория: что уже работает, как устроен код, какие функции есть в CLI/GUI и какие модули за что отвечают. Пользовательская документация по разделам лежит в docs/.


1. Зачем проект существует

Студент пишет отчёт в расширенном Markdown (диалект md2gost). Конвертер сам:

  • оформляет DOCX стилями Times New Roman, полями 30/10/20/20 мм, интервалом 1.5;
  • нумерует рисунки, таблицы, листинги, формулы;
  • собирает содержание и список источников;
  • рисует UML / C4 / Mermaid;
  • проверяет структуру по ТЗ (--check);
  • при необходимости режет длинные таблицы и листинги через Microsoft Word и пишет «Продолжение…».

Исходный форк: benzlokzik/md2gost. Здесь — своя линия: профили МИРЭА/ПИС/АПИД, GUI, схемы, стили JSON, Word COM, FODT, LaTeX.


2. Три продукта в одном репозитории

Пакет Entry point Результат Когда
md2gost python -m md2gost / md2gost-gui .docx основной путь, Word
md2fodt python -m md2fodt .fodt LibreOffice, без Word
md2latex python -m md2latex каталог XeLaTeX (+ --pdf) PDF через шаблон МИРЭА
word2md python -m word2md / md2gost файл.docx .md импорт DOCX → диалект md2gost

Общий диалект разметки: спецразделы # *ВВЕДЕНИЕ, метки %id, ссылки @Рисунок:id, таблицы с ^/>, формулы $$, библиография [n]: ….

Полнота реализации не одинаковая:

  • md2gost — полный конвейер (стили, профили, диаграммы, checker, GUI, Word COM).
  • md2fodt — v1: текст, заголовки, списки, таблицы с merge, картинки, листинги, простые ссылки, библиография. Нет PlantUML, нет «Продолжение таблицы», нет полного паритета PIS/АПИД.
  • md2latex — тот же диалект → content.tex + копия latex/mirea/. Таблицы идут в longtable с настоящим «Продолжение таблицы N» (это умеет LaTeX, не Word).
  • word2md — эвристический DOCX → диалект md2gost (стили Caption/Heading, подписи, таблицы, Code, формулы OMML). Не восстанавливает UML/Mermaid и исходные %id.

3. Как запустить

pip install -e .
python -m md2gost                          # GUI
python -m md2gost report.md -o report.docx --type coursework --check
python -m word2md report.docx -o report.md
python -m md2fodt report.md -o report.fodt
python -m md2latex report.md -o report_latex --pdf

Windows exe: build-exe.batdist\md2gost.exe (двойной клик — GUI; из консоли работает как CLI; перед сборкой тянет plantuml.jar и portable Graphviz).
Быстрая сборка: build-exe-fast.bat + md2gost.fast.spec.

Для режима продолжения таблиц/листингов word (по умолчанию): Windows + Microsoft Word + pip install pywin32 (опциональная группа [word]).


4. Архитектура md2gost (главный конвейер)

Один движок на CLI и GUI. GUI только собирает ConvertRequest и зовёт convert().

.md
 │
 ├─ checker.check_markdown()          # если --check / --check-only
 │
 ├─ profiles.preprocess_markdown()    # «ёлочки», тире; не трогает UML/Mermaid
 │
 ├─ Parser (marko + extended_markdown)
 │     └─ RenderableFactory → список Renderable
 │
 ├─ biblio_processor.fold_bibliography()
 ├─ Heading / ToC / Table / Listing: режимы нумерации и continuation
 ├─ label_pass.assign_numbers() + resolve @Тип:id
 │
 ├─ Renderer.process()                # LayoutTracker, секции, альбом, колонтитулы
 ├─ TocProcessor.process()            # native TOC field или ручная сборка
 │
 ├─ [опционально] docxcompose: титул + задание + тело
 ├─ document.save()
 ├─ [если word] word_fix.fix_continuations()   # COM: реальные разрывы страниц
 └─ [если --check-pages] page_fill_check       # эвристика полупустых страниц

Ключевые типы:

  • ConvertRequest / ConvertResult — контракт CLI↔GUI (md2gost/pipeline.py).
  • DocProfile — правила типа работы (md2gost/profiles.py).
  • StyleConfig — поля страницы + стили абзацев (md2gost/style_config.py).
  • Renderable — элемент, который умеет себя нарисовать в DOCX с учётом высоты страницы.

5. Что уже умеет пользователь (функции продукта)

5.1. Типы документов (--type)

Тип Стили Нумерация объектов Источники Структура
practice mirea по разделам 1.1, 2.1 57, ≤5 лет Введение, разделы, заключение, список, приложения
coursework mirea то же 57, ≤5 лет то же
vkr mirea то же ≥10 в каждом разделе списка, ссылки [1.5] + приложение «Графический материал»
PIS_custom pis_custom сквозная 1, 2, 3 не обязательны H1 = «Практическая работа №N. …»; H1 по центру ПРОПИСНЫМИ; H2 с абзацным отступом
APID_coursework mirea по разделам 720, ≤5 лет обязательные главы «Теоретические…» / «Прикладные…» и пункты 2.1–2.4

Реализация: PROFILES и get_profile() в profiles.py. Стили пресетов: preset_mirea(), preset_pis_custom().

5.2. CLI (все флаги)

Точка входа: md2gost/__main__.pybuild_parser(), request_from_args(), main().

Флаг По умолчанию Что делает
filename нет → GUI .md или .docx с --check-pages
--gui открыть окно (можно сразу передать .md)
-o / --output рядом с md, то же имя выходной DOCX
-t / --template md2gost/Template.docx шаблон Word
--type practice профиль документа
--heading-numbering manual manual — цифры из md, автонумерация Word выкл.; auto — нумерует Word, цифры в начале заголовка снимаются
--toc native native — поле Word TOC; manual — сборка по LayoutTracker
--table-continuation word word / off / soft / legacy / caption
--listing-continuation word то же для листингов
--table-repeat-header выкл. шапка на фрагментах после word-split
--emdash-to-hyphen выкл. «—» → «-»
--hr-pagebreak выкл. --- / *** / ___ → разрыв страницы
--title / --assignment DOCX титула и бланка задания (склейка через docxcompose)
--auto-title / --no-auto-title автотитул из yaml/```title (по умолчанию выкл.)
--student / --group ФИО и группа для автотитула (иначе md2gost.user.json)
--doc-author-from / --doc-author os / профиль автор в свойствах DOCX: os (имя ОС), student, custom
--doc-title / --doc-subject / --doc-keywords / --doc-comments / --doc-category / --doc-last-modified-by см. профиль остальные поля File → сведения; пустые comments — без штампа md2gost
--check / --check-only / --strict проверка ТЗ; --strict → код выхода 1 при ошибках
--check-pages полупустые страницы через Word COM (эвристика, не влияет на --strict)
--syntax-highlighting Pygments в листингах
--plantuml-jar / --kroki-url локальный рендер диаграмм
--diagram-fallback remote remote / local / off
--diagram-format png png или svg (svgBlip + PNG-запасной)
--diagram-scale 2.0 качество PNG PlantUML (размер на странице как при 1)
--schemes авто путь к md2gost.schemes.json
--styles авто оверлей md2gost.styles.json
--debug отладочная сетка в документе + открыть файл

Занятый выходной файл: timestamped_output_path() пишет имя_ГГГГ-ММ-ДД-ЧЧ-ММ.docx.

Windowed exe: _argv_needs_console() + _enable_windows_console() — консоль появляется только для CLI/--help, не для GUI.

5.3. GUI (Tkinter)

Модуль md2gost/gui.py, класс Md2GostApp. Entry: md2gost-gui / python -m md2gost без файла / --gui.

Уже есть:

  • зона Drop: перетаскивание .md (tkinterdnd2, иначе Win32 WM_DROPFILES, иначе клик → диалог);
  • основные параметры: тип, нумерация заголовков, TOC, continuation таблиц/листингов, тире, --- → разрыв, проверки ТЗ, вёрстка, открыть после сборки;
  • Настройки → Файлы: шаблон, титул, задание, стили JSON, выходной путь;
  • Настройки → Студент…: ФИО и группа (первый запуск);
  • Настройки → Метаданные…: свойства DOCX (автор, название, тема, теги, примечание) в md2gost.user.json;
  • Настройки → Диаграммы: jar, Kroki, fallback, формат, масштаб, статус движка, скачать PlantUML, сброс кэша includes;
  • Шаблоны UML: CRUD схем (md2gost.schemes.json) — добавить / дублировать / удалить / сохранить / открыть JSON;
  • Справка: Инструкция, Документация (вшитые docs/*.md), Схемы, Промпт для ИИ (каталог prompts/ + кнопки схем);
  • конвертация в фоне (threading), лог в окне, тултипы, меню «Дебаг» на одну следующую сборку;
  • если выходной DOCX занят — timestamp-имя, как в CLI.

Конвертация не блокирует окно: _convert() → поток → _on_done().

5.4. Диалект Markdown

Реализовано в extended_markdown/ (расширение Marko + GFM) и RenderableFactory.

Элемент Синтаксис Поведение
Спецраздел без номера # *ВВЕДЕНИЕ ПРОПИСНЫЕ, без автономера раздела
Содержание # *СОДЕРЖАНИЕ + [TOC] native поле Word или ручная сборка
Рисунок-файл ![…](file.png "%id Подпись") нумерация + @Рисунок:id
Таблица %id Подпись перед таблицей подпись «Таблица N — …»
Merge ячеек ^ rowspan, > colspan OOXML vMerge / gridSpan; через разрыв страницы merge не переносится
Листинг %id + code fence Courier New, опционально Pygments
Диаграмма %id + ```uml / uml-c4 / mermaid / idef0 / dfd Рисунок; флаги +listing, +landscape
Формула %eq1 + $$…$$ + @Формула:eq1 номер только если есть ссылка
Инлайн-формула $…$ OMML в абзаце
Ссылка на объект @Рисунок:id, @Таблица:id, @Листинг:id, @Формула:id подстановка номера
Источник [1] в тексте, [1]: … в списке ВКР: [1.5], цитата [2.18, c. 21-25]
Разрыв страницы --- + --hr-pagebreak иначе HR игнорируется
Жирный / курсив / зачёркивание / ссылки / списки обычный MD поддерживается

Автоправки текста (preprocess_markdown):

  • "..." → «…» (эвристика, не внутри %…);
  • слово - словослово — слово (если не --emdash-to-hyphen);
  • внутри оград UML/Mermaid/схем не трогает кавычки и тире;
  • в списке источников каждый [n]: выносится в отдельный абзац (separate_biblio_lines).

5.5. Схемы и диаграммы

Встроенные id (md2gost/diagrams/schemes.json): c4, c4context, c4component, usecase.

Слои загрузки (позже побеждает): встроенный шаблон → md2gost.schemes.json рядом с приложением (создаётся при первом запуске, не перезаписывается) → рядом с .md--schemes.

Рендер UML:

  1. Java + plantuml.jar (вшитый / %LOCALAPPDATA%\md2gost\ / --plantuml-jar);
  2. локальный Kroki (KROKI_URL / --kroki-url);
  3. https://kroki.io при --diagram-fallback remote.

Mermaid — локально (браузер / QuickJS) или Kroki. IDEF0 — оградка ```idef0, локальный Pillow (рамка NIST). DFD — оградка ```dfd, пакет data-flow-diagram → вшитый/кэш/PATH Graphviz (scripts/fetch_graphviz.py, GUI «Скачать Graphviz») или Kroki.

Кэш картинок: {каталог_md}/.md2gost-cache/.
Кэш !include URL: md2gost.include-cache.json + include-cache/.

Альбомная страница: флаг +landscape у подписи — отдельная секция A4 landscape с вертикальным центрированием, затем снова книжная. Один section break (без пустой книжной страницы перед альбомом).

5.6. Кастомные стили JSON

Файл md2gost.styles.json (рядом с .md и/или --styles). Deep-merge поверх пресета типа. Неизвестный ключ или имя стиля — ошибка (StyleConfigError).

Можно менять поля page (мм) и поля стилей абзацев: шрифт, кегль, жирный/курсив/прописные, выравнивание, отступы, интервал 1.0/1.5, page_break_before, keep_with_next, widow_control.

Не в JSON: табы оглавления (считаются от ширины полосы), отступы списков, цвет (всегда чёрный), формулы из шаблона.

5.7. Проверка ТЗ (--check)

Модуль md2gost/checker/__init__.py. Возвращает Issue(id, severity, message, line).

Уже проверяется:

  • обязательные разделы по профилю (СОДЕРЖАНИЕ, ВВЕДЕНИЕ, ЗАКЛЮЧЕНИЕ, список; для ПИС — практические работы; для ВКР — «Графический материал»; для АПИД — 6 обязательных заголовков);
  • [TOC];
  • спецразделы должны быть # *…, лучше ПРОПИСНЫМИ;
  • запрет «рис.», «табл.», сносок [^1], графы «№ п/п»;
  • ссылки [n] во введении/заключении запрещены;
  • число и возраст источников; для ВКР — по разделам списка; порядок первого упоминания;
  • висячие / неиспользованные метки %id / @Тип:id;
  • запрещённые буквы приложений (Ё З Й О Ч Ь Ы Ъ);
  • перечень приложений после # *ПРИЛОЖЕНИЯ, если приложений ≥ 2;
  • маркеры merge ^/> в шапке и > в первом столбце;
  • подсказка про «Продолжение…», если continuation = off/soft.

--strict падает только на severity == "error". --check-pages — отдельная эвристика, в strict не входит.

5.8. Продолжение таблиц и листингов

DOCX сам не умеет писать «Продолжение Таблицы N» только со 2-й страницы.

Режим Поведение
word (по умолчанию) После save Word COM режет по реальной пагинации, вставляет подпись
off / soft Одна таблица/листинг, пагинацию делает Word, без автоподписи
legacy Резка по оценке высоты LayoutTracker + page_break_before (могут быть дыры)
caption То же + явный PageBreak

Оценка высоты ≠ вёрстка Word — поэтому legacy/caption помечены как неточные.

5.9. Титул, задание, колонтитулы

--title / --assignment: пустая оболочка из шаблона + docxcompose (титул, разрыв, задание, разрыв, тело).
На секциях титула/задания колонтитул без номера страницы; дальше — сквозная нумерация, поле PAGE, TNR 12 по центру. После TOC начинается секция тела с номерами.

Если в документе нет TOC — номер ставится на единственную секцию.

Автотитул (по умолчанию выкл.; CLI --auto-title / галочка в GUI; явный --title отключает генератор): см. docs/title.md. Кратко: md2gost/title_page.py заполняет bundled TitleTemplate.docx из info_conv.yaml и/или блока ```title, ФИО/группа — md2gost.user.json или --student/--group. GUI: первый запуск и Настройки → Студент….

Свойства DOCX (после склейки титула, перед save): doc_metadata.apply_document_metadata. По умолчанию автор = getuser(), примечание «Создано при помощи md2gost (ТЗ МИРЭА)», created/modified = сейчас, revision = 1. GUI Настройки → Метаданные… / флаги --doc-*. Профиль — блок metadata в md2gost.user.json.

5.10. Приложения

  • Буквы: А Б В Г Д Е Ж И К … (без Ё З Й О Ч Ь Ы Ъ) — APPENDIX_LETTERS в numberer.py.
  • ## Приложение А Название оформляется как приложение.
  • Если после # *ПРИЛОЖЕНИЯ нет перечня, а приложений несколько — Renderer сам вставляет список «Приложение А — …». Если автор уже написал перечень — не дублирует.

5.11. Промпты для ИИ

Файл Назначение
prompts/generate-md.md диалект md2gost vs обычный MD
prompts/generate-mirea-report.md полный отчёт ГОСТ / МИРЭА
prompts/generate-pis-custom-report.md итоговый отчёт ПИС
prompts/emulate-student.md голос: человечный текст, не отчёт ИИ

В GUI: выбор промпта + чекбоксы схем → в конец дописываются ai-prompt и макросы из md2gost.schemes.json (compose_prompt()).

5.12. Сборка и поставка

  • pyproject.toml: hatchling, пакеты md2gost, md2latex, md2fodt; в wheel вшиваются Template.docx, mml2omml, diagrams, latex/mirea, prompts, docs.
  • md2gost.spec / md2gost.fast.spec — PyInstaller (вшивают plantuml.jar и при наличии vendor/graphviz).
  • scripts/fetch_plantuml.py — скачать jar.
  • scripts/fetch_graphviz.py — скачать portable Graphviz в md2gost/vendor/graphviz (для DFD в exe).
  • scripts/md2gost_exe.py — обёртка exe.
  • scripts/pyi_rth_mplbackend.py — runtime hook matplotlib для PyInstaller.
  • scripts/check_page_fill.bas — макрос Word для той же эвристики вёрстки.
  • scripts/md2pdf.ps1 / md2pdf.sh — обёртки LaTeX→PDF.
  • CI: .github/workflows/pytest.yml (Python 3.11, flake8, pytest); example-generator.yml.

6. Карта модулей md2gost и функции кода

Ниже — публичные и важные внутренние функции уже реализованные. Приватные _foo указаны, если без них не понять модуль.

6.1. Точки входа и пайплайн

md2gost/__init__.py

  • package_dir() — каталог пакета (и _MEIPASS в frozen exe).

md2gost/__main__.py

  • build_parser() — argparse.
  • request_from_args(args)ConvertRequest.
  • _argv_needs_console(argv), _enable_windows_console().
  • main().

md2gost/pipeline.py

  • ConvertRequest, ConvertResult.
  • default_output_path(filename), timestamped_output_path(path), default_template_path().
  • open_document(path) — macOS open / Windows startfile / xdg-open.
  • _fix_front_matter_after_compose(...) — сброс PAGE на титуле/задании, сквозная нумерация.
  • convert(req, log=None) — весь конвейер, ошибки в ConvertResult, не пробрасывает исключение наружу. Перед save — apply_document_metadata.
  • should_launch_gui(filename, gui_flag).
  • _CallbackLogHandler — логи md2gost в GUI/CLI.

md2gost/doc_metadata.py

  • DocumentMetadata, DEFAULT_DOC_COMMENTS, AUTHOR_SOURCES.
  • os_user(), clip_core() (лимит 255 символов python-docx).
  • resolve_document_metadata(...) — профиль + CLI/request.
  • apply_document_metadata(document, meta) — core properties + даты + revision=1.

md2gost/user_profile.py

  • UserProfile (student, group, metadata), load_user_profile / save_user_profilemd2gost.user.json.

md2gost/converter.py

  • класс Converter: читает md, применяет стили, парсит, нумерует, рендерит.
  • convert(), свойства document, style_config, raw_markdown, doc_type, heading_numbering.

6.2. Профили и стили

md2gost/profiles.py

  • константы: DOC_TYPES, HEADING_NUMBERING_MODES, TOC_MODES, TABLE_CONTINUATION_MODES, LISTING_CONTINUATION_MODES, NUMBERING_SCOPES, STYLE_PRESETS.
  • DocProfile — поля min/max источников, sectional_biblio, require_graphic_appendix, style_preset, numbering_scope, флаги структуры, require_apid_kr_structure.
  • get_profile(doc_type).
  • fix_russian_quotes, fix_dashes, replace_emdash_with_hyphen.
  • set_emdash_to_hyphen, emdash_to_hyphen_enabled, dash_separator.
  • preprocess_markdown, separate_biblio_lines.
  • find_formula_refs@Формула: / @Formula:.
  • current_year().

md2gost/style_config.py

  • StyleConfigError.
  • PageSpec.merge/to_dict/require_complete.
  • ParagraphStyleSpec.merge/to_dict.
  • StyleConfig.merge/to_dict.
  • preset_mirea(), preset_pis_custom(), get_preset(name).
  • style_config_from_dict, load_styles_file, resolve_style_config (пресет ← рядом с md ← --styles).

md2gost/styles.py

  • apply_style_config(document, config) — поля, секции, табы TOC, стили абзацев.
  • apply_mirea_styles, apply_pis_custom_styles.
  • apply_document_styles(...) — пресет + оверлей, возвращает итоговый StyleConfig.
  • Внутри: _set_run_font (блокирует тему Word: Calibri/синий), _ensure_style, _fix_toc_tab_stops.

md2gost/page_geometry.py

  • глобальные поля MARGIN_*, MARGIN_PRESETS, apply_margin_preset.
  • is_landscape_section, apply_section_geometry, content_size.
  • apply_centered_page_footer, clear_section_footer, ensure_continuous_page_numbers.

6.3. Разбор Markdown

md2gost/extended_markdown/

  • __init__.py — Marko + GFM + Extension: Equation, Reference, Caption, Table, TOC, Heading, InlineEquation, Image.
  • heading.py# * → ненумерованный.
  • caption.py — строка %id текст +listing +landscape.
  • table.py — GFM-таблица + ^/> + _resolve_merge_restarts.
  • image.py%id в title картинки.
  • equation.py — блочная $$.
  • inline_formula.py$…$.
  • reference.py@Тип:id.
  • toc.py[TOC].

md2gost/parser_.py

  • Parser.parse() — пропускает пустые строки; копит CaptionInfo; HR без флага игнорирует; иначе factory.create.

md2gost/renderable_factory.py

  • RenderableFactory.create (singledispatch): Paragraph, Heading, FencedCode/CodeBlock → Listing или DiagramFigure, Equation, List, Table, TOC, ThematicBreak → PageBreak.
  • _create_runs — жирный/курсив/зачёркивание, код, картинки, инлайн-формулы, @ссылки, гиперссылки.

6.4. Нумерация и ссылки

md2gost/numberer.py

  • Numberer(mode="section"|"continuous"): enter_section, enter_appendix, next_number, resolve, register_label.
  • Режим section: 1.1 / Б.1, счётчики сбрасываются на разделе/приложении.
  • Режим continuous: 1, 2, 3 на весь документ (ПИС).

md2gost/label_pass.py

  • LabelRegistry.put/get/get_display (алиасы Рисунок/Figure/Таблица/…).
  • assign_numbers(renderables, numbered_equations, numbering_scope).
  • resolve_pending_in_renderables, set_active_registry, resolve_reference.

Формулы нумеруются только если на них есть @Формула:… в исходнике.

6.5. Рендер в DOCX

md2gost/renderer.py — класс Renderer

  • process(renderables) — основной цикл.
  • Секции: фронт без номеров → после TOC тело с PAGE; _enter_landscape / _exit_landscape.
  • _ensure_appendix_index — автоперечень приложений.
  • Нумерация объектов через Numberer (если не skip_numbering — в Converter нумерация уже в label_pass).
  • Спецзаголовки: СОДЕРЖАНИЕ / СПИСОК — по центру; Введение / Заключение / ПРИЛОЖЕНИЯ — слева как H1.

md2gost/layout_tracker.py

  • LayoutState — текущая/оставшаяся высота, номер страницы.
  • LayoutTrackeradd_height, can_fit_to_page, new_page, set_page_size (книга ↔ альбом).

md2gost/renderable/

Класс Файл Роль
Renderable renderable.py абстрактный render()
Paragraph / Link paragraph.py абзац, runs, картинки, ссылки, инлайн-формулы
Heading heading.py уровни 19, manual/auto, снятие Word numbering, strip ведущих цифр
Table table.py сетка, merge, continuation, +landscape
Listing listing.py код, Pygments (DocxParagraphPygmentsFormatter), continuation
Image image.py файл-рисунок + подпись
DiagramFigure diagram.py рендер схемы + опциональный Listing исходника
Equation equation.py блочная формула OMML + номер справа
Caption / CaptionInfo caption.py «Рисунок 1.1 — …»
List list.py маркированные/нумерованные, вложенность
ToC toc.py native field TOC \o "1-3" \h \z \u или ручные строки с табами
PageBreak page_break.py явный разрыв
RequiresNumbering requires_numbering.py интерфейс нумеруемых объектов
ParagraphSizer / шрифты paragraph_sizer.py, find_font.py оценка высоты абзаца (FreeType)

md2gost/docx_elements.py

  • create_table, create_table_row, create_table_cell, apply_cell_merge, set_table_box_borders, фиксация ширины в twips.

md2gost/docx_svg.py

  • attach_svg_blip(run, inline_shape, svg_path) — вектор + PNG fallback.

md2gost/latex_math.py

  • latex_to_omml(latex) — latex2mathml + XSLT mml2omml.
  • inline_omml(omml) — дроби в линейный вид для инлайна.

md2gost/toc_processor.py

  • TocProcessor.process — native: updateFields при открытии Word; manual: страницы из Heading.rendered_page (СОДЕРЖАНИЕ в оглавление не попадает).

md2gost/debugger.py

  • плавающая сетка страниц в документе (--debug): Debugger, add_float_picture, new_pic_anchor.

md2gost/util.py

  • create_element — низкоуровневый OOXML.

6.6. Библиография

md2gost/bibliography.py

  • BiblioEntry, extract_year, parse_biblio_block, find_citations.
  • Bibliography(...) — ленивая обёртка над renderable (чтобы checker не тянул docx).

md2gost/biblio_processor.py

  • entries_from_text — несколько [n]: внутри одного абзаца (Marko склеивает строки).
  • extract_bibliography_from_markdown — плоский список или секции для ВКР.
  • fold_bibliography(renderables, parent, raw_markdown) — заменяет абзацы списка на Bibliography.

md2gost/bibliography_renderable.py — отрисовка пунктов списка стилем Bibliography.

6.7. Диаграммы

md2gost/diagram_schemes.py

  • DiagramScheme (id, title, docs, ai-prompt, includes, prefix/postfix, theme).
  • bundled_schemes_path, user_schemes_path, ensure_user_schemes.
  • load_schemes_from_path, save_schemes, load_merged_schemes.
  • scheme_id_from_lang, is_diagram_lang, get_scheme, get_schemes, reload_schemes, configure_schemes.
  • apply_scheme, prepare_with_schemes.

md2gost/diagram_includes.py

  • кэш HTTP !include: resolve_url, resolve_include_ref, rewrite_http_includes_in_source, reset_include_cache, cache_entry_count.

md2gost/diagram_renderer.py

  • configure_diagrams(...), DiagramConfig, DiagramRenderResult.
  • prepare_source, render_diagram.
  • resolve_plantuml_jar, fetch_plantuml_jar, iter_plantuml_candidates, diagram_engine_status.
  • рендер jar / Kroki / пара png+svg; масштаб scale в исходник PlantUML.
  • локальные типы LOCAL_ONLY_TYPES (idef0, dfd): Pillow, без jar/Kroki.

md2gost/idef0.py — DSL IDEF0 + Pillow/SVG.

md2gost/dfd.py — обёртка pbauermeister/dfd: DSL → DOT → vendor/system Graphviz / Kroki (write_dfd_outputs, fetch_graphviz).

md2gost/diagrams/schemes.json, C4 *.puml.

6.8. Word COM и вёрстка

md2gost/word_fix.py

  • parse_caption_text, find_page_break_row, continuation_label, caption_style_name.
  • fix_continuations(path, tables, listings, repeat_header)FixResult.
  • Внутри: до 5 проходов Repaginate + Split, рамки листингов, опциональный повтор шапки.

md2gost/page_fill_check.py

  • PageMetric, PageFillIssue.
  • evaluate_page_fill(pages) — чистая эвристика (порог пустого низа 40%, пропускает альбом, последнюю страницу, фронт, конец раздела, «в основном рисунок/таблица»).
  • check_docx_page_fill(path), format_page_fill_report.

6.9. Checker (функции проверок)

md2gost/checker/__init__.py:

  • check_structure, check_apid_kr_structure, check_pis_headings, check_special_headings.
  • check_forbidden_abbreviations, check_citations_in_intro_conclusion.
  • check_bibliography, check_object_refs, check_appendices.
  • check_continuation_hints, check_table_merge.
  • check_markdown(...) — оркестратор.
  • format_report(issues).

6.10. GUI, DnD, справка

md2gost/gui.py

  • _make_root, _combo_values/_combo_key/_display, _Tooltip, _tip.
  • Md2GostApp: меню, окна файлов/студента/метаданных/диаграмм/схем/справки, браузер docs, сборка промпта, DnD, _collect()ConvertRequest, _convert.
  • run_gui(initial), main().

md2gost/dnd.py

  • parse_tkdnd_files, normalize_drop_paths, first_markdown, enable_file_drop.
  • Win32: _WinDropHook, _Win32DropApi, _query_drop_files.

md2gost/help_content.py

  • константы USAGE_HELP, SCHEMES_HELP.
  • prompt_search_dirs, load_prompt_catalog, scheme_prompt_block, compose_prompt.
  • docs_search_dirs, load_docs_catalog.

7. md2fodt — что уже есть

Пакет md2fodt/.

Файл Функции
__main__.py main() — CLI: файл, -o, --emdash-to-hyphen
converter.py convert_md_to_fodt(md, output, emdash_to_hyphen)
emitter.py emit_body, emit_fodt; эмиттеры heading/paragraph/image/table/code/list/equation; merge ^/>
styles.py styles_xml(), automatic_styles_xml() — TNR 14, поля ГОСТ
escape.py escape_text, xml_id

Картинки встраиваются base64. Нет диаграмм PlantUML и нет «Продолжение таблицы».


8. md2latex — что уже есть

Пакет md2latex/ + шаблон latex/mirea/ (вендор mirea-ninja/Latex-Template-for-Report-Diploma-Thesis).

Файл Функции
__main__.py main(), _run_xelatex (latexmk или 2 прохода xelatex)
converter.py package_template_dir(), convert_md_to_latex_project(md, out, titlepage) — копирует шаблон, пишет content.tex
emitter.py emit_document; _emit_longtable с \endfirsthead / \endhead и «Продолжение таблицы N»
escape.py escape_text, escape_verbatim_for_listing, latex_label

Флаги: -o каталог, --titlepage PDF титула, --pdf, --xelatex-passes.


8.1. word2md — импорт DOCX

Пакет word2md/. Эвристика: стили md2gost, иначе ГОСТ-текст подписей/заголовков.

Файл Роль
__main__.py CLI: .docx, -o, --media-dir, --keep-toc-pages, --pagebreaks
pipeline.py ImportRequest / ImportResult / convert_docx()
walker.py обход body, склейка Code/списков, postprocess_blocks (продолжения)
classify.py Heading / Caption / Code / библио / спецразделы
captions.py Рисунок / Таблица / Листинг + parse_caption_text из md2gost
tables.py merge → ^/>, детект формульной таблицы
omml.py OMML → читаемая формула
media.py выгрузка word/media
emit.py IR → диалект md2gost
refs.py Рисунок 1.1@Рисунок:fig1_1

Точки входа также: python -m md2gost report.docx, GUI «Импорт DOCX→MD».


9. Тесты — что покрыто

Каталог tests/, CI гоняет pytest.

Файл Что проверяет
test_pipeline.py GUI/CLI развилка, пути, DnD, argparse, HR→pagebreak, промпты, docs catalog, listing continuation
test_mirea_tz.py Numberer, checker (coursework/PIS/ВКР/АПИД), препроцесс, TOC, заголовки, приложения, библио, page-fill эвристика, стили H1
test_style_config.py merge оверлея, неизвестные ключи, CLI побеждает файл рядом с md, применение к Document
test_table_merge.py ^/>, OOXML merge, checker merge, режимы continuation
test_word_fix.py разбор подписей, индекс разрыва, COM smoke (если нет Word — мягко)
test_landscape.py геометрия альбома, секции, картинки/таблицы/листинги, один section break
test_layout_tracker.py страницы и остаток высоты
test_paragraph.py / test_paragraph_sizer.py абзацы и измерение шрифта
test_diagram_renderer.py схемы, кэш, mermaid, svg, jar, +listing/+landscape
test_idef0.py DSL IDEF0, PNG/SVG, интеграция render_diagram
test_dfd.py DFD data-flow-diagram, mock Graphviz/Kroki, интеграция render_diagram
test_md2fodt.py escape, каркас FODT, запись файла
test_md2latex.py longtable continuation, генерация проекта
test_word2md.py подписи, спецзаголовки, @ссылки, продолжения таблиц, DOCX→MD, round-trip
extended_mardown/formula.py формулы (unittest)

Нет полного e2e «открыть Word и сравнить каждую страницу» в Linux CI (шрифты ставятся, Word COM — нет).


10. Документация и примеры

Пользовательские страницы (те же вшиты в exe, GUI: Справка → Документация):

Файл Содержание
ReadMe.md краткий старт репозитория
docs/README.md оглавление docs
docs/quickstart.md установка, exe, типы
docs/markdown.md диалект
docs/schemes.md UML/Mermaid, JSON схем
docs/types.md профили работ
docs/cli-gui.md флаги ↔ GUI
docs/styles.md JSON стилей
docs/prompts.md ИИ-промпты
docs/word2md.md импорт DOCX → Markdown
md2gost/README.md справка пакета (подробнее про continuation и диаграммы)
prompts/README.md как копировать промпты
examples/example.md, examples/pis_custom.md образцы
examples/md2gost.styles.json пример оверлея стилей

11. Зависимости

Обязательные (pyproject.toml): python-docx, marko, docxcompose, freetype-py, pillow, requests, latex2mathml, pygments, lxml.

Опционально: pywin32 (Word COM), matplotlib (сборка exe / отладка), tkinterdnd2 (удобный DnD в GUI).

Внешние рантаймы: Java + plantuml.jar или Kroki; Graphviz (вшитый/кэш/PATH) для DFD; для PDF — XeLaTeX / latexmk и шрифт Times New Roman.


12. Что в репозитории, но не продукт

Черновики и чужой код рядом с пакетами. Это не часть pip install / exe:

  • корень: main.py, main12.py, mm2.pymm5.py, asd.py, parser.py, font.py, _audit_tmp.py, tmp_listing_word.md, todo.txt;
  • ad/ — черновые отчёты;
  • _paco_extract/ — выгрузки методичек ПАЦО;
  • Other_Code/ — справка OOXML, docx-js, скрипты pack/unpack/validate (не импортируется md2gost);
  • артефакты сборки build-fast/, кэши диаграмм.

todo.txt сейчас: «оценки с текстом через сам Word, а не предугадывание» — частично закрыто режимом word.


13. Чего нет / ограничения (честно)

  • DFD: пакет data-flow-diagram в зависимостях; картинка — вшитый/кэш/PATH Graphviz или Kroki; балансировка уровней не проверяется.
  • FODT и LaTeX не догоняют md2gost по GUI, checker, схемам, профилям PIS/АПИД, Word COM.
  • «Продолжение таблицы» в чистом DOCX без Word невозможно точно (нет longtable). Без Word — off или неточный legacy/caption.
  • --check-pages даёт ложные срабатывания; это эвристика.
  • Merge ячеек не живёт через границу разрезанной таблицы.
  • Цвет текста в стилях не настраивается (всегда чёрный).
  • Профиль paco_custom упомянут в комментарии page_geometry, отдельного типа в DOC_TYPES нет.
  • Нумерация заголовков H4+ в стилях JSON не описана (в Word уровни 1–9 у Heading есть).

14. Типичные сценарии «уже работает»

  1. Практика / курсовая МИРЭА: # *ВВЕДЕНИЕ# 1 … … список [1]:--type practice|coursework --check --strict.
  2. ВКР: раздельный список, ссылки [1.5], приложение «Графический материал».
  3. ПИС: # Практическая работа №1. …--type PIS_custom, сквозные Рисунок 1, 2, 3.
  4. АПИД: обязательные 2 главы и 2.1–2.4, источники 720.
  5. UML в отчёте: %id Подпись + ```uml-c4 — PNG/SVG в Word, опционально +listing и +landscape.
  6. Широкая таблица: %id … +landscape.
  7. Длинная таблица на Windows: режим word → COM режет и пишет «Продолжение Таблицы N».
  8. Свой вуз/кафедра: md2gost.styles.json меняет поля и H1 без правки кода.
  9. Своя схема: GUI «Шаблоны UML» или JSON с includes/prefix/ai-prompt.
  10. Черновик через ИИ: промпт из GUI + схемы → .md → конвертер.
  11. Только проверить готовый DOCX: python -m md2gost report.docx --check-pages.
  12. Без Word: python -m md2fodt или python -m md2latex --pdf.

15. Поток данных одним абзацем

Пользователь кладёт .md (и опционально титул/задание/JSON стилей/схем). convert() читает текст, при необходимости гоняет checker, препроцессит кавычки/тире, парсит Marko-расширением в дерево, фабрика делает Renderable, библиография сворачивается в особые абзацы, объектам раздаются номера по профилю, @ссылки заменяются на «Рисунок 2.1», Renderer кладёт OOXML в очищенный Template.docx с оценкой высоты страницы, TocProcessor дописывает содержание, pipeline склеивает титул, сохраняет DOCX, при режиме word открывает файл в Word и режет таблицы/листинги по настоящей пагинации. GUI делает ровно то же, только параметры собирает из формы.


16. Где править, если добавлять функцию

Хочешь Куда
Новый тип работы profiles.PROFILES + checker + стили пресета
Новое поле CLI/GUI __main__.build_parser, ConvertRequest, gui._collect/_apply_request
Новый элемент Markdown extended_markdown/ + RenderableFactory + класс в renderable/
Новая проверка ТЗ checker/__init__.py → вызов из check_markdown
Новая UML-схема «из коробки» md2gost/diagrams/schemes.json (+ .puml при необходимости)
Новое поле стиля style_config.STYLE_FIELD_KEYS + ParagraphStyleSpec + _apply_paragraph_spec
Паритет FODT/LaTeX md2fodt/emitter.py / md2latex/emitter.py

Файл сгенерирован по состоянию исходников репозитория (пакет 0.1.0). Пользовательские howto — в docs/. Этот файл — инвентарь возможностей и кода.