This commit is contained in:
+683
@@ -0,0 +1,683 @@
|
||||
# GhostEditor / md2gost — полное описание проекта
|
||||
|
||||
Версия пакета: **0.1.0**. Python **≥ 3.10**.
|
||||
Репозиторий: конвертер учебных отчётов **Markdown → DOCX** по методичке РТУ МИРЭА (ГОСТ 7.32-2017) и профилям **ПИС / АПИД**. Рядом — два дополнительных пайплайна: **FODT** (LibreOffice) и **LaTeX → PDF**.
|
||||
|
||||
Этот файл — карта всего репозитория: что уже работает, как устроен код, какие функции есть в CLI/GUI и какие модули за что отвечают. Пользовательская документация по разделам лежит в [`docs/`](docs/).
|
||||
|
||||
---
|
||||
|
||||
## 1. Зачем проект существует
|
||||
|
||||
Студент пишет отчёт в расширенном Markdown (диалект md2gost). Конвертер сам:
|
||||
|
||||
- оформляет DOCX стилями Times New Roman, полями 30/10/20/20 мм, интервалом 1.5;
|
||||
- нумерует рисунки, таблицы, листинги, формулы;
|
||||
- собирает содержание и список источников;
|
||||
- рисует UML / C4 / BPMN / Mermaid;
|
||||
- проверяет структуру по ТЗ (`--check`);
|
||||
- при необходимости режет длинные таблицы и листинги через Microsoft Word и пишет «Продолжение…».
|
||||
|
||||
Исходный форк: [benzlokzik/md2gost](https://github.com/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 через шаблон МИРЭА |
|
||||
|
||||
Общий диалект разметки: спецразделы `# *ВВЕДЕНИЕ`, метки `%id`, ссылки `@Рисунок:id`, таблицы с `^`/`>`, формулы `$$`, библиография `[n]: …`.
|
||||
|
||||
Полнота реализации **не одинаковая**:
|
||||
|
||||
- **md2gost** — полный конвейер (стили, профили, диаграммы, checker, GUI, Word COM).
|
||||
- **md2fodt** — v1: текст, заголовки, списки, таблицы с merge, картинки, листинги, простые ссылки, библиография. Нет PlantUML, нет «Продолжение таблицы», нет полного паритета PIS/АПИД.
|
||||
- **md2latex** — тот же диалект → `content.tex` + копия `latex/mirea/`. Таблицы идут в `longtable` с настоящим «Продолжение таблицы N» (это умеет LaTeX, не Word).
|
||||
|
||||
---
|
||||
|
||||
## 3. Как запустить
|
||||
|
||||
```bash
|
||||
pip install -e .
|
||||
python -m md2gost # GUI
|
||||
python -m md2gost report.md -o report.docx --type coursework --check
|
||||
python -m md2fodt report.md -o report.fodt
|
||||
python -m md2latex report.md -o report_latex --pdf
|
||||
```
|
||||
|
||||
Windows exe: `build-exe.bat` → `dist\md2gost.exe` (двойной клик — GUI; из консоли работает как CLI).
|
||||
Быстрая сборка: `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` | 5–7, ≤5 лет | Введение, разделы, заключение, список, приложения |
|
||||
| `coursework` | mirea | то же | 5–7, ≤5 лет | то же |
|
||||
| `vkr` | mirea | то же | ≥10 **в каждом** разделе списка, ссылки `[1.5]` | + приложение «Графический материал» |
|
||||
| `PIS_custom` | pis_custom | сквозная `1, 2, 3` | не обязательны | H1 = «Практическая работа №N. …»; H1 по центру ПРОПИСНЫМИ; H2 с абзацным отступом |
|
||||
| `APID_coursework` | mirea | по разделам | 7–20, ≤5 лет | обязательные главы «Теоретические…» / «Прикладные…» и пункты 2.1–2.4 |
|
||||
|
||||
Реализация: `PROFILES` и `get_profile()` в `profiles.py`. Стили пресетов: `preset_mirea()`, `preset_pis_custom()`.
|
||||
|
||||
### 5.2. CLI (все флаги)
|
||||
|
||||
Точка входа: `md2gost/__main__.py` → `build_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) |
|
||||
| `--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, выходной путь;
|
||||
- **Настройки → Диаграммы**: 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 или ручная сборка |
|
||||
| Рисунок-файл | `` | нумерация + `@Рисунок:id` |
|
||||
| Таблица | `%id Подпись` перед таблицей | подпись «Таблица N — …» |
|
||||
| Merge ячеек | `^` rowspan, `>` colspan | OOXML `vMerge` / `gridSpan`; через разрыв страницы merge не переносится |
|
||||
| Листинг | `%id` + code fence | Courier New, опционально Pygments |
|
||||
| Диаграмма | `%id` + ` ```uml ` / `uml-c4` / `bpmn` / `mermaid` | Рисунок; флаги `+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`, `bpmn`.
|
||||
|
||||
Слои загрузки (позже побеждает): встроенный шаблон → `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 — только Kroki. **IDEF0 / DFD конвертер не рисует** — только готовый PNG.
|
||||
|
||||
Кэш картинок: `{каталог_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 — номер ставится на единственную секцию.
|
||||
|
||||
### 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` | итоговый отчёт ПИС |
|
||||
|
||||
В 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.
|
||||
- `scripts/fetch_plantuml.py` — скачать jar.
|
||||
- `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`, не пробрасывает исключение наружу.
|
||||
- `should_launch_gui(filename, gui_flag)`.
|
||||
- `_CallbackLogHandler` — логи md2gost в GUI/CLI.
|
||||
|
||||
**`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` — текущая/оставшаяся высота, номер страницы.
|
||||
- `LayoutTracker` — `add_height`, `can_fit_to_page`, `new_page`, `set_page_size` (книга ↔ альбом).
|
||||
|
||||
**`md2gost/renderable/`**
|
||||
|
||||
| Класс | Файл | Роль |
|
||||
|--------|------|------|
|
||||
| `Renderable` | `renderable.py` | абстрактный `render()` |
|
||||
| `Paragraph` / `Link` | `paragraph.py` | абзац, runs, картинки, ссылки, инлайн-формулы |
|
||||
| `Heading` | `heading.py` | уровни 1–9, 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.
|
||||
|
||||
**`md2gost/diagrams/`** — `schemes.json`, `BPMN.puml`, 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](https://github.com/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`.
|
||||
|
||||
---
|
||||
|
||||
## 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` | схемы, BPMN, кэш, mermaid, svg, jar, `+listing`/`+landscape` |
|
||||
| `test_md2fodt.py` | escape, каркас FODT, запись файла |
|
||||
| `test_md2latex.py` | longtable continuation, генерация проекта |
|
||||
| `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/BPMN, JSON схем |
|
||||
| `docs/types.md` | профили работ |
|
||||
| `docs/cli-gui.md` | флаги ↔ GUI |
|
||||
| `docs/styles.md` | JSON стилей |
|
||||
| `docs/prompts.md` | ИИ-промпты |
|
||||
| `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; для PDF — XeLaTeX / latexmk и шрифт Times New Roman.
|
||||
|
||||
---
|
||||
|
||||
## 12. Что в репозитории, но не продукт
|
||||
|
||||
Черновики и чужой код рядом с пакетами. Это **не** часть `pip install` / exe:
|
||||
|
||||
- корень: `main.py`, `main12.py`, `mm2.py`…`mm5.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` сейчас: «ожидаем BPMN в mermaid» и «оценки с текстом через сам Word, а не предугадывание» — второе частично закрыто режимом `word`.
|
||||
|
||||
---
|
||||
|
||||
## 13. Чего нет / ограничения (честно)
|
||||
|
||||
- IDEF0 и DFD конвертер не рисует.
|
||||
- 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, источники 7–20.
|
||||
5. **UML в отчёте:** `%id Подпись` + ` ```uml-c4 ` / ` ```bpmn ` — 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/`. Этот файл — инвентарь возможностей и кода.*
|
||||
@@ -14,7 +14,9 @@ Windows: `build-exe.bat` → `dist\md2gost.exe` (двойной клик — GUI
|
||||
|
||||
## Документация
|
||||
|
||||
Полное описание — в [`docs/`](docs/):
|
||||
Полная карта проекта (что уже умеет, пайплайны, модули): [`PROJECT.md`](PROJECT.md).
|
||||
|
||||
Пользовательская документация — в [`docs/`](docs/):
|
||||
|
||||
| Раздел | Содержание |
|
||||
|--------|------------|
|
||||
|
||||
+49
-45
@@ -1,70 +1,46 @@
|
||||
@echo off
|
||||
setlocal EnableExtensions
|
||||
chcp 65001 >nul
|
||||
cd /d "%~dp0"
|
||||
chcp 65001 >nul 2>&1
|
||||
|
||||
set "DO_PAUSE=1"
|
||||
set "PYI_CLEAN="
|
||||
for %%A in (%*) do (
|
||||
if /i "%%~A"=="nopause" set "DO_PAUSE=0"
|
||||
if /i "%%~A"=="clean" set "PYI_CLEAN=--clean"
|
||||
)
|
||||
if /i "%~1"=="nopause" set "DO_PAUSE=0"
|
||||
if /i "%~2"=="nopause" set "DO_PAUSE=0"
|
||||
if /i "%~1"=="clean" set "PYI_CLEAN=--clean"
|
||||
if /i "%~2"=="clean" set "PYI_CLEAN=--clean"
|
||||
|
||||
echo === md2gost: быстрая сборка exe (onefile, шрифты + plantuml.jar) ===
|
||||
echo === md2gost: быстрая сборка exe, onefile, шрифты и plantuml.jar ===
|
||||
echo Каталог: %CD%
|
||||
echo Spec: md2gost.fast.spec
|
||||
echo Кэш: build-fast\ (без --clean, пока не передадите clean)
|
||||
echo Кэш: build-fast\ без --clean, пока не передадите clean
|
||||
echo.
|
||||
|
||||
where python >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo Python не найден в PATH. Установите Python 3.10+ и отметьте "Add python.exe to PATH".
|
||||
goto :fail
|
||||
)
|
||||
if errorlevel 1 goto :nopython
|
||||
|
||||
python -c "import sys; raise SystemExit(0 if sys.version_info >= (3, 10) else 1)"
|
||||
if errorlevel 1 (
|
||||
echo Нужен Python 3.10 или новее.
|
||||
python --version
|
||||
goto :fail
|
||||
)
|
||||
python -c "import sys; raise SystemExit(sys.hexversion < 0x030A0000)"
|
||||
if errorlevel 1 goto :oldpython
|
||||
|
||||
echo [1/4] Зависимости ...
|
||||
python -c "import PyInstaller, matplotlib, docx, marko, lxml, pygments, PIL, freetype, latex2mathml, requests, docxcompose" 1>nul 2>nul
|
||||
if errorlevel 1 (
|
||||
echo Ставлю проект + PyInstaller + matplotlib ...
|
||||
python -m pip install -q -e . "pyinstaller>=6.0" "matplotlib>=3.7"
|
||||
if errorlevel 1 (
|
||||
echo Не удалось поставить зависимости.
|
||||
goto :fail
|
||||
)
|
||||
) else (
|
||||
echo Уже стоят, pip пропускаю.
|
||||
)
|
||||
if not errorlevel 1 goto :deps_ok
|
||||
echo Ставлю проект + PyInstaller + matplotlib ...
|
||||
python -m pip install -q -e . "pyinstaller>=6.0" "matplotlib>=3.7"
|
||||
if errorlevel 1 goto :pipfail
|
||||
:deps_ok
|
||||
|
||||
if not exist "md2gost\Template.docx" (
|
||||
echo Нет md2gost\Template.docx — сборка бессмысленна.
|
||||
goto :fail
|
||||
)
|
||||
if not exist "md2gost\Template.docx" goto :notemplate
|
||||
|
||||
echo [2/4] PlantUML jar (обязателен, вшивается в exe) ...
|
||||
echo [2/4] PlantUML jar, обязателен, вшивается в exe ...
|
||||
python scripts\fetch_plantuml.py
|
||||
if not exist "md2gost\vendor\plantuml.jar" (
|
||||
echo Нет md2gost\vendor\plantuml.jar — portable exe без jar не собираем.
|
||||
goto :fail
|
||||
)
|
||||
if not exist "md2gost\vendor\plantuml.jar" goto :nojar
|
||||
|
||||
echo [3/4] PyInstaller onefile, кэш build-fast ...
|
||||
python -m PyInstaller --noconfirm %PYI_CLEAN% --workpath build-fast --distpath dist md2gost.fast.spec
|
||||
if errorlevel 1 (
|
||||
echo PyInstaller завершился с ошибкой.
|
||||
goto :fail
|
||||
)
|
||||
if errorlevel 1 goto :pyifail
|
||||
|
||||
if not exist "dist\md2gost.exe" (
|
||||
echo dist\md2gost.exe не появился.
|
||||
goto :fail
|
||||
)
|
||||
if not exist "dist\md2gost.exe" goto :noexe
|
||||
|
||||
echo.
|
||||
echo [4/4] Готово:
|
||||
@@ -74,10 +50,38 @@ echo Двойной клик — GUI. Из консоли: md2gost.exe report.md
|
||||
echo Повторно без clean — быстрее за счёт кэша Analysis.
|
||||
echo Полный пересбор: build-exe-fast.bat clean
|
||||
echo.
|
||||
|
||||
if "%DO_PAUSE%"=="1" pause
|
||||
exit /b 0
|
||||
|
||||
:nopython
|
||||
echo Python не найден в PATH. Установите Python 3.10+ и отметьте "Add python.exe to PATH".
|
||||
goto :fail
|
||||
|
||||
:oldpython
|
||||
echo Нужен Python 3.10 или новее.
|
||||
python --version
|
||||
goto :fail
|
||||
|
||||
:pipfail
|
||||
echo Не удалось поставить зависимости.
|
||||
goto :fail
|
||||
|
||||
:notemplate
|
||||
echo Нет md2gost\Template.docx — сборка бессмысленна.
|
||||
goto :fail
|
||||
|
||||
:nojar
|
||||
echo Нет md2gost\vendor\plantuml.jar — portable exe без jar не собираем.
|
||||
goto :fail
|
||||
|
||||
:pyifail
|
||||
echo PyInstaller завершился с ошибкой.
|
||||
goto :fail
|
||||
|
||||
:noexe
|
||||
echo dist\md2gost.exe не появился.
|
||||
goto :fail
|
||||
|
||||
:fail
|
||||
echo.
|
||||
echo Сборка не удалась.
|
||||
|
||||
+35
-30
@@ -1,54 +1,35 @@
|
||||
@echo off
|
||||
setlocal EnableExtensions
|
||||
chcp 65001 >nul
|
||||
cd /d "%~dp0"
|
||||
chcp 65001 >nul 2>&1
|
||||
|
||||
echo === md2gost: сборка exe ===
|
||||
echo Каталог: %CD%
|
||||
echo.
|
||||
|
||||
where python >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo Python не найден в PATH. Установите Python 3.10+ и отметьте "Add python.exe to PATH".
|
||||
goto :fail
|
||||
)
|
||||
if errorlevel 1 goto :nopython
|
||||
|
||||
python -c "import sys; raise SystemExit(0 if sys.version_info >= (3, 10) else 1)"
|
||||
if errorlevel 1 (
|
||||
echo Нужен Python 3.10 или новее.
|
||||
python --version
|
||||
goto :fail
|
||||
)
|
||||
python -c "import sys; raise SystemExit(sys.hexversion < 0x030A0000)"
|
||||
if errorlevel 1 goto :oldpython
|
||||
|
||||
echo [1/4] Зависимости проекта + PyInstaller + matplotlib ...
|
||||
python -m pip install -q -e . "pyinstaller>=6.0" "matplotlib>=3.7"
|
||||
if errorlevel 1 (
|
||||
echo Не удалось поставить зависимости.
|
||||
goto :fail
|
||||
)
|
||||
if errorlevel 1 goto :pipfail
|
||||
|
||||
if not exist "md2gost\Template.docx" (
|
||||
echo Нет md2gost\Template.docx — сборка бессмысленна.
|
||||
goto :fail
|
||||
)
|
||||
if not exist "md2gost\Template.docx" goto :notemplate
|
||||
|
||||
echo [2/4] PlantUML jar (вшивается в exe, если скачается^) ...
|
||||
echo [2/4] PlantUML jar, вшивается в exe если скачается ...
|
||||
python scripts\fetch_plantuml.py
|
||||
if not exist "md2gost\vendor\plantuml.jar" (
|
||||
echo Предупреждение: plantuml.jar нет — в exe диаграммы пойдут через kroki.io.
|
||||
)
|
||||
|
||||
echo [3/4] PyInstaller (один файл, без консоли; CLI подцепит консоль сам^) ...
|
||||
echo [3/4] PyInstaller, один файл, без консоли; CLI подцепит консоль сам ...
|
||||
python -m PyInstaller --noconfirm --clean md2gost.spec
|
||||
if errorlevel 1 (
|
||||
echo PyInstaller завершился с ошибкой.
|
||||
goto :fail
|
||||
)
|
||||
if errorlevel 1 goto :pyifail
|
||||
|
||||
if not exist "dist\md2gost.exe" (
|
||||
echo dist\md2gost.exe не появился.
|
||||
goto :fail
|
||||
)
|
||||
if not exist "dist\md2gost.exe" goto :noexe
|
||||
|
||||
echo.
|
||||
echo [4/4] Готово:
|
||||
@@ -56,11 +37,35 @@ echo %CD%\dist\md2gost.exe
|
||||
echo.
|
||||
echo Двойной клик — GUI. Из консоли: md2gost.exe report.md -o report.docx
|
||||
echo.
|
||||
|
||||
if /i "%~1"=="nopause" goto :eof
|
||||
pause
|
||||
exit /b 0
|
||||
|
||||
:nopython
|
||||
echo Python не найден в PATH. Установите Python 3.10+ и отметьте "Add python.exe to PATH".
|
||||
goto :fail
|
||||
|
||||
:oldpython
|
||||
echo Нужен Python 3.10 или новее.
|
||||
python --version
|
||||
goto :fail
|
||||
|
||||
:pipfail
|
||||
echo Не удалось поставить зависимости.
|
||||
goto :fail
|
||||
|
||||
:notemplate
|
||||
echo Нет md2gost\Template.docx — сборка бессмысленна.
|
||||
goto :fail
|
||||
|
||||
:pyifail
|
||||
echo PyInstaller завершился с ошибкой.
|
||||
goto :fail
|
||||
|
||||
:noexe
|
||||
echo dist\md2gost.exe не появился.
|
||||
goto :fail
|
||||
|
||||
:fail
|
||||
echo.
|
||||
echo Сборка не удалась.
|
||||
|
||||
@@ -14,4 +14,6 @@
|
||||
|
||||
Исходный код конвертера: [`md2gost/`](../md2gost/). Примеры: [`examples/`](../examples/).
|
||||
|
||||
Полная карта репозитория (архитектура, все функции CLI/GUI и модули кода): [`PROJECT.md`](../PROJECT.md).
|
||||
|
||||
В GUI: **Справка → Документация** — тот же набор страниц (вшит в exe).
|
||||
|
||||
Reference in New Issue
Block a user