"""Usage text and AI prompt files for the GUI pages.""" from __future__ import annotations import sys from pathlib import Path from . import package_dir USAGE_HELP = """md2gost — Markdown → DOCX (ТЗ МИРЭА / ГОСТ 7.32) КАК ПОЛЬЗОВАТЬСЯ ОКНОМ 1. Перетащите .md в верхнюю область (или кликните по ней). 2. Выберите тип документа и параметры в блоке «Основные». Шаблон / титул / задание — Настройки → Файлы. ФИО и группа студента — Настройки → Студент… (спрашивают при первом запуске). Свойства DOCX (автор, название, примечание) — Настройки → Метаданные…. PlantUML / Mermaid / Kroki — Настройки → Диаграммы. Свои UML-схемы — меню «Шаблоны UML». 3. Нажмите «Конвертировать». Документ сохранится рядом с исходником (или по пути «Выходной DOCX»). Если файл уже есть и вы откажетесь перезаписывать — сохранится как имя_гггг-мм-дд-ЧЧ-ММ.docx. Дебаг (меню сверху) — следующая сборка с отладочными данными в документе. Типы: practice (по умолчанию) / coursework / vkr — ГОСТ МИРЭА; PIS_custom — отчёт по практикам ПИС; APID_coursework — курсовая АПИД. Полезные галочки • «—» → «-» — заменить типографское тире на дефис (по умолчанию **выкл.**; методичка требует «—»). • --- → разрыв страницы — по умолчанию выкл. (строка --- игнорируется). Вкл. — page break в Word. • Смещение страниц — начальный номер PAGE в теле (пусто = сквозной; 1 = тело с 1). • Проверить по ТЗ — замечания по структуре, «рис.», источникам. • Проверить вёрстку в Word — полупустые страницы (эвристика, возможны ложные срабатывания; нужны Word + pywin32). • Титул / задание — отдельные DOCX, вставляются перед телом отчёта. Автотитул — галочка «Автотитул» / CLI `--auto-title` (по умолчанию **выкл.**): info_conv.yaml рядом с .md + опционально блок ```title (number, year…); ФИО/группа — Настройки → Студент… или --student / --group. Явный путь к титулу отключает генератор. Подробно: docs/title.md. • Свойства файла Word — Настройки → Метаданные… / --doc-author-from, --doc-author, --doc-title, --doc-comments…. По умолчанию автор = имя Windows, примечание «Создано при помощи md2gost (ТЗ МИРЭА)». CLI (тот же движок) python -m md2gost report.md -o report.docx --type coursework --check python -m md2gost report.md --auto-title --student "Иванов И. И." --group ИНБО-31-23 python -m md2gost report.md --doc-author-from student --doc-comments "" python -m md2gost report.docx -o report.md python -m word2md report.docx python -m md2gost --gui md2gost.exe report.md --type PIS_custom --title title.docx md2gost.exe report.md --schemes path/to/md2gost.schemes.json md2gost.exe report.md --styles path/to/md2gost.styles.json Импорт Word → Markdown Перетащите .docx или кнопка «Импорт DOCX→MD». Подписи, таблицы, спецразделы переводятся в диалект md2gost. UML/Mermaid из картинок не восстанавливаются. Подробнее: docs/word2md.md. Стили JSON (опционально) Оверлей поверх пресета типа документа (--type). Файл md2gost.styles.json рядом с .md или --styles / Настройки → Файлы → «Стили JSON». Меняет поля страницы и параметры стилей абзацев (Normal, Heading 1–3, подписи…). В шаблон DOCX стили руками добавлять не нужно. Подробнее: docs/styles.md. СИНТАКСИС MARKDOWN Спецразделы (без номера, ПРОПИСНЫЕ, звёздочка): # *СОДЕРЖАНИЕ [TOC] # *ВВЕДЕНИЕ # *ЗАКЛЮЧЕНИЕ # *СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ # *ПРИЛОЖЕНИЯ (перечень «Приложение А — …» собирается сам из ## Приложение А Название; можно написать вручную — тогда автосписок не дублируется) ## Приложение А Название Нумерованные разделы: # 1 Название ## 1.1 Подраздел Точку в конце заголовка не ставить. СОДЕРЖАНИЕ и СПИСОК — по центру; Введение / Заключение / ПРИЛОЖЕНИЯ — слева. Рисунок Текст со ссылкой на @Рисунок:arch. ![описание](images/arch.png "%arch Название рисунка") В тексте пишите «Рисунок», не «рис.» Таблица %tbl1 Название | A | B | |---|---| | 1 | 2 | Ссылка: @Таблица:tbl1 Склеивание: ^ — ячейка сверху (rowspan), > — ячейка слева (colspan). Не ставить ^/> в шапке; > — не в первом столбце. Листинг %code1 Название ```python print("ok") ``` Диаграмма (PlantUML / Mermaid / схемы) → рисунок %usecase1 Диаграмма прецедентов +listing ```uml @startuml actor User User --> (Login) @enduml ``` Широкая схема/таблица на альбомной странице: %arch1 Архитектура +landscape ```uml-c4 … ``` Mermaid (локально: браузер / QuickJS; иначе Kroki): %seq Последовательность +listing ```mermaid sequenceDiagram Alice->>Bob: hello ``` IDEF0 (контекст A-0, рамка NIST): %a0 Контекст +landscape ```idef0 title Распорядиться товаром node A-0 [A0] Распорядиться товаром <- Спрос ^ Нормативная документация -> Товар v Персонал ``` DFD (pbauermeister/dfd → Graphviz вшитый/PATH / Kroki): %dfd0 Контекстная DFD ```dfd style context entity Client Клиент process System Система учёта заявок Client --> System заявка System --> Client статус ``` +listing — ещё и листинг с исходником. +landscape — отдельная альбомная страница (A4, повёрт на 90°) вокруг рисунка/таблицы, затем снова книжная. Языки: uml, plantuml, mermaid / mmd, idef0, dfd / data-flow-diagram, или uml- / из файла схем (c4, usecase, archimate, …). Формат в Word: PNG по умолчанию (PlantUML, локальный Mermaid, IDEF0 и DFD ~2× для чёткости); --diagram-format svg — вектор + PNG-запасной (Word 2016+). Подробнее — Справка → Схемы и раздел ниже в инструкции. Формула (номер только если есть ссылка) %eq1 $$ E = mc^2 $$ См. @Формула:eq1 Источники В тексте: [1] (в DOCX — ссылка на пункт списка) В списке: [1]: Иванов И. И. Название. — М.: Наука, 2023. — 120 с. Разрыв страницы По умолчанию --- игнорируется. Галочка «--- → разрыв страницы» или --hr-pagebreak: пустая строка, ---, пустая строка. Нумерация заголовков manual — цифры уже в md (# 1 …); auto — нумерует Word. Содержание native — поле Word (обновить при открытии); manual — собирает md2gost. Продолжение таблиц / листингов word — по умолчанию: после сборки Word COM режет по реальной пагинации и вставляет «Продолжение…» (нужны Windows + Word + pywin32). Также уводит таблицу целиком, если внизу страницы зависли только название или название + шапка граф (методичка: рис. Г.3). off — одна таблица, Word сам переносит строки; без авто«Продолжение». Защита от сирот: keep_with_next у подписи/шапки и оценка «подпись+шапка+1 строка» при рендере (без COM слабее, чем word). legacy / caption — режем по оценке высоты в md2gost (может не совпасть с Word). Промпт для ИИ — Справка → Промпт для ИИ: выберите промпт, при необходимости включите схемы (C4, usecase, …) кнопками — макросы допишутся в конец — скопируйте в ChatGPT / Cursor / Copilot, затем дайте тему и черновик. Документация — Справка → Документация: встроенный просмотр docs/*.md (вшито в exe; внешняя папка docs/ не обязательна). """ SCHEMES_HELP = """СХЕМЫ ДИАГРАММ (PlantUML) Зачем В markdown пишете только «тело» диаграммы. Обёртка (@startuml, !include, тема) берётся из схемы в файле md2gost.schemes.json. Первый запуск Рядом с программой (рядом с md2gost.exe или в текущей папке при python -m) создаётся md2gost.schemes.json из встроенного шаблона. При каждом запуске схемы с author=md2gost синхронизируются с шаблоном приложения (добавление новых id, обновление, удаление исчезнувших вроде bpmn). Схемы с пустым или другим author не трогаются. Если правите встроенную схему в GUI и сохраняете — author сбрасывается, чтобы следующая миграция не затёрла ваши правки. Оградка в markdown ```uml — обычный PlantUML (или ```plantuml) ```uml-c4 — схема с id «c4» (то же, что ```c4) ```uml-usecase — схема «usecase» ```uml-archimate — ArchiMate 3.2 (макросы Business_*, Rel_Serving, …) ```mermaid / ```mmd — Mermaid локально (браузер / Chromium / QuickJS) или через Kroki ```idef0 — IDEF0 (FIPS 183): боксы, стрелки ICOM, рамка NIST; локальный Pillow ```dfd / ```data-flow-diagram — DFD (pbauermeister/dfd): process/entity/store, --> ; Graphviz (вшитый / «Скачать Graphviz» / PATH) или Kroki Встроенные пресеты PlantUML: c4, c4context, c4component, usecase. Пример %arch Архитектура +listing ```uml-c4 Person(user, "Студент") System(app, "Портал") Rel(user, app, "логин") ``` Поля схемы в JSON title — подпись в GUI version — версия схемы author — автор docs — шпаргалка синтаксиса (чтобы вспомнить макросы) ai-prompt — заготовка промпта для ИИ / будущего MCP includes — список файлов или http(s):// URL на .puml prefix — текст перед телом (часто @startuml) postfix — текст после тела (часто @enduml) theme — опционально !theme … Свои схемы 1. Меню «Шаблоны UML» в GUI — добавьте / отредактируйте и сохраните. 2. Или откройте md2gost.schemes.json в редакторе («Открыть JSON» / «Открыть файл схем»). 3. CLI: --schemes путь.json; также подхватывается md2gost.schemes.json рядом с .md. Кэш includes из интернета URL из includes (и !include https://… внутри .puml) при первом рендере скачиваются. Индекс — md2gost.include-cache.json (только пары URL → файл). Файлы лежат в папке include-cache/. Уже скачанные файлы не перезаписываются. Повторный рендер без сети берёт путь из индекса. «Сбросить кэш includes» в Настройки → Диаграммы или в «Шаблоны UML» удаляет индекс и только файлы, перечисленные в нём. Чего нет Балансировка родитель/потомок DFD между уровнями не проверяется автоматически. Рендер UML: Java + plantuml.jar (локально) → иначе локальный Kroki → иначе kroki.io. Mermaid: системный Chrome/Edge → Playwright Chromium (кнопка / --install-chromium) → QuickJS (mermaidx, офлайн) → локальный Kroki → kroki.io. IDEF0: Pillow, без сети и Java. DFD: data-flow-diagram → Graphviz (dot/neato) или Kroki graphviz. Нужны: Graphviz (вшитый / «Скачать Graphviz» / PATH) либо Kroki; пакет data-flow-diagram ставится с md2gost. Формат: PNG по умолчанию (PlantUML / локальный Mermaid ~scale 2 для чёткости, размер на странице как при 1; --diagram-scale); --diagram-format svg — PNG + SVG (svgBlip в Word 2016+). +landscape у %подписи — альбомная страница под широкий рисунок/таблицу. """ PROMPT_FILES = ( ("generate-md.md", "Markdown для md2gost"), ("generate-mirea-report.md", "МИРЭА / ГОСТ (курсовая, практика, ВКР)"), ("generate-pis-custom-report.md", "ПИС — отчёт по практическим работам"), ("emulate-student.md", "Стиль: человечный текст, не отчёт ИИ"), ) def prompt_search_dirs() -> list[Path]: dirs: list[Path] = [] here = Path(package_dir()) dirs.append(here / "prompts") dirs.append(here.parent / "prompts") if getattr(sys, "frozen", False): mei = getattr(sys, "_MEIPASS", None) if mei: dirs.append(Path(mei) / "prompts") dirs.append(Path(sys.executable).resolve().parent / "prompts") seen: set[str] = set() out: list[Path] = [] for path in dirs: key = str(path.resolve()) if path.exists() else str(path) if key in seen: continue seen.add(key) out.append(path) return out def load_prompt_catalog() -> list[tuple[str, str, str]]: """Return list of (filename, title, text). Missing files are skipped.""" catalog: list[tuple[str, str, str]] = [] dirs = prompt_search_dirs() for name, title in PROMPT_FILES: text = None for folder in dirs: candidate = folder / name if candidate.is_file(): text = candidate.read_text(encoding="utf-8") break if text: catalog.append((name, title, text)) return catalog def scheme_prompt_block(scheme) -> str: """Format one DiagramScheme for appending to an AI prompt.""" sid = getattr(scheme, "id", "") or "" title = (getattr(scheme, "title", None) or sid).strip() lines = [ f"## Схема: {title} (`{sid}`)", "", f"Оградка в markdown: ```uml-{sid} или ```{sid}", "", ] ai = (getattr(scheme, "ai_prompt", None) or "").strip() if ai: lines.append(ai) lines.append("") docs = (getattr(scheme, "docs", None) or "").strip() if docs: lines.append("Макросы / шпаргалка:") lines.append(docs) lines.append("") return "\n".join(lines).rstrip() + "\n" def compose_prompt(base: str, schemes: list | None = None) -> str: """ Base prompt text plus optional scheme blocks (order preserved). schemes: iterable of DiagramScheme (or objects with id/title/docs/ai_prompt). """ text = (base or "").rstrip() if not schemes: return text + ("\n" if text else "") parts = [text, "", "---", "", "# Дополнение: выбранные схемы диаграмм", ""] for scheme in schemes: parts.append(scheme_prompt_block(scheme)) parts.append("") return "\n".join(parts).rstrip() + "\n" def docs_search_dirs() -> list[Path]: dirs: list[Path] = [] here = Path(package_dir()) dirs.append(here / "docs") dirs.append(here.parent / "docs") if getattr(sys, "frozen", False): mei = getattr(sys, "_MEIPASS", None) if mei: dirs.append(Path(mei) / "docs") dirs.append(Path(sys.executable).resolve().parent / "docs") seen: set[str] = set() out: list[Path] = [] for path in dirs: key = str(path.resolve()) if path.exists() else str(path) if key in seen: continue seen.add(key) out.append(path) return out def _doc_title_from_text(filename: str, text: str) -> str: for line in text.splitlines(): stripped = line.strip() if stripped.startswith("#"): return stripped.lstrip("#").strip() or Path(filename).stem return Path(filename).stem def load_docs_catalog() -> list[tuple[str, str, str]]: """ Return list of (filename, title, text) from the first existing docs/ folder. README.md first, then other *.md alphabetically. """ folder: Path | None = None for path in docs_search_dirs(): if path.is_dir(): folder = path break if folder is None: return [] files = sorted(p for p in folder.glob("*.md") if p.is_file()) if not files: return [] readme = [p for p in files if p.name.lower() == "readme.md"] rest = [p for p in files if p.name.lower() != "readme.md"] ordered = readme + rest catalog: list[tuple[str, str, str]] = [] for path in ordered: try: text = path.read_text(encoding="utf-8") except OSError: continue catalog.append((path.name, _doc_title_from_text(path.name, text), text)) return catalog