BigUpdate 0.5.0
Python application / build (push) Has been cancelled

- add Local Render Mermaid
- add page-starе для указания смещения страниц
- add Гиперссылки в документе на списки литературы
This commit is contained in:
Igor20264
2026-09-07 09:54:33 +03:00
parent ac0aa33399
commit 1a5b35eb54
29 changed files with 4118 additions and 69 deletions
+92 -10
View File
@@ -65,7 +65,7 @@ TABLE_LABELS = {
}
FALLBACK_LABELS = {
"remote": "Авто: локально, иначе интернет (kroki.io)",
"local": "Только этот компьютер (нужна Java)",
"local": "Только этот компьютер (без kroki.io)",
"off": "Не рисовать диаграммы",
}
FORMAT_LABELS = {
@@ -257,6 +257,7 @@ class Md2GostApp:
self.plantuml_var = tk.StringVar()
self.kroki_var = tk.StringVar()
self.scale_var = tk.StringVar(value="2")
self.page_start_var = tk.StringVar(value="")
self.highlight_var = tk.BooleanVar(value=False)
self.debug_var = tk.BooleanVar(value=False)
self.output_var.trace_add("write", self._on_output_edited)
@@ -351,8 +352,8 @@ class Md2GostApp:
win = tk.Toplevel(self.root)
win.title("Настройки — Диаграммы")
win.configure(bg=PAPER)
win.minsize(560, 420)
win.geometry("680x520")
win.minsize(560, 480)
win.geometry("700x600")
win.transient(self.root)
extra = ttk.Frame(win, padding=12)
extra.pack(fill=tk.BOTH, expand=True)
@@ -363,7 +364,8 @@ class Md2GostApp:
text=(
"Блоки ```uml / ```uml-c4 / ```bpmn / ```mermaid сами станут рисунками.\n"
"Схемы редактируются в меню «Шаблоны UML» (файл md2gost.schemes.json).\n"
"UML: сначала PlantUML + Java, иначе интернет (kroki.io). Mermaid — только через Kroki."
"UML: PlantUML + Java, иначе Kroki. Mermaid: системный браузер → "
"Chromium → QuickJS → Kroki (kroki.io остаётся запасным)."
),
style="Hint.TLabel",
wraplength=640,
@@ -375,16 +377,25 @@ class Md2GostApp:
status_row.grid(row=1, column=0, columnspan=2, sticky="ew", pady=(0, 8))
status_row.columnconfigure(0, weight=1)
self.diag_status = ttk.Label(status_row, text="", style="Hint.TLabel", wraplength=480, justify=tk.LEFT)
self.diag_status.grid(row=0, column=0, sticky="w")
self.diag_status.grid(row=0, column=0, sticky="w", rowspan=2)
btn_dl = ttk.Button(status_row, text="Скачать PlantUML", command=self._download_plantuml)
btn_dl.grid(row=0, column=1, sticky="e", padx=(8, 0))
_tip(btn_dl, "Скачать plantuml.jar для локальной отрисовки (нужна Java)")
btn_cr = ttk.Button(
status_row, text="Скачать headless Chromium", command=self._download_chromium,
)
btn_cr.grid(row=1, column=1, sticky="e", padx=(8, 0), pady=(4, 0))
_tip(
btn_cr,
"Скачать Chromium для Mermaid в %LOCALAPPDATA%\\md2gost "
"(если нет системного Edge/Chrome)",
)
self._combo(
extra, 2, "Как рисовать",
self.fallback_var,
_combo_values(FALLBACK_LABELS, ("remote", "local", "off")),
tip="Локально (PlantUML+Java), через интернет или не рисовать",
tip="Локально (PlantUML / браузер / QuickJS), через интернет или не рисовать",
)
self._combo(
extra, 3, "Формат схем",
@@ -393,12 +404,12 @@ class Md2GostApp:
tip="PNG везде; SVG — вектор в Word 2016+ (PNG рядом как запасной)",
)
ttk.Label(extra, text="Scale PNG (PlantUML)").grid(row=4, column=0, sticky="w", padx=(0, 8), pady=3)
ttk.Label(extra, text="Scale PNG").grid(row=4, column=0, sticky="w", padx=(0, 8), pady=3)
scale_row = ttk.Frame(extra)
scale_row.grid(row=4, column=1, sticky="w", pady=3)
scale_entry = ttk.Entry(scale_row, textvariable=self.scale_var, width=8)
scale_entry.pack(side=tk.LEFT)
_tip(scale_entry, "Качество растра PlantUML; на странице размер как при 1")
_tip(scale_entry, "Качество растра PlantUML / локального Mermaid; на странице размер как при 1")
ttk.Label(
scale_row,
text=" качество; на странице размер как при 1",
@@ -422,7 +433,10 @@ class Md2GostApp:
tip="Пусто — вшитый jar или скачанный автоматически")
ttk.Label(
extra,
text="Свой Kroki — только если у вас крутится свой сервер. Пусто = сначала localhost:8000, потом kroki.io.",
text=(
"Свой Kroki — запасной путь (и для UML без Java). Пусто = localhost:8000, потом kroki.io. "
"Mermaid сначала рисуется локально (браузер / QuickJS)."
),
style="Hint.TLabel",
wraplength=640,
).grid(row=8, column=0, columnspan=2, sticky="w", pady=(6, 0))
@@ -822,8 +836,24 @@ class Md2GostApp:
self._combo(main, 4, "Продолжение листингов", self.listing_var, _combo_values(TABLE_LABELS, LISTING_CONTINUATION_MODES),
tip="То же для листингов; word требует Windows + Word + pywin32")
ttk.Label(main, text="Смещение страниц").grid(row=5, column=0, sticky="w", padx=(0, 8), pady=3)
page_row = ttk.Frame(main)
page_row.grid(row=5, column=1, sticky="w", pady=3)
page_entry = ttk.Entry(page_row, textvariable=self.page_start_var, width=8)
page_entry.pack(side=tk.LEFT)
_tip(
page_entry,
"Начальный номер PAGE в колонтитуле тела. Пусто — сквозная нумерация Word; "
"например 1 — тело с 1 (титул/задание без номера)",
)
ttk.Label(
page_row,
text=" пусто = сквозной; 1 = тело с первой",
style="Hint.TLabel",
).pack(side=tk.LEFT)
flags = ttk.Frame(main)
flags.grid(row=5, column=0, columnspan=2, sticky="w", pady=(8, 0))
flags.grid(row=6, column=0, columnspan=2, sticky="w", pady=(8, 0))
checks = [
("Заменять «—» на «-»", self.emdash_var, "Типографское тире → дефис (методичка обычно требует «—»)"),
("--- → разрыв страницы", self.hr_pagebreak_var, "Строка --- станет page break в Word"),
@@ -1260,6 +1290,45 @@ class Md2GostApp:
"Можно ничего не делать — диаграммы нарисует kroki.io.",
)
def _download_chromium(self) -> None:
from .mermaid_renderer import install_playwright_chromium, playwright_browsers_dir, playwright_available
if not playwright_available():
messagebox.showerror(
"md2gost",
"Пакет playwright не установлен.\n"
"Установите: pip install playwright\n"
"Mermaid всё равно может рисоваться через QuickJS (mermaidx) или Kroki.",
)
return
dest = playwright_browsers_dir()
self._append_log(f"Скачиваю headless Chromium → {dest}")
self.root.update_idletasks()
def work() -> None:
ok = install_playwright_chromium()
self.root.after(0, lambda: self._on_chromium_installed(ok, dest))
import threading
threading.Thread(target=work, daemon=True).start()
def _on_chromium_installed(self, ok: bool, dest) -> None:
self._refresh_diagram_status()
if ok:
messagebox.showinfo(
"md2gost",
f"Chromium установлен:\n{dest}\n\n"
"Будет использоваться для локального Mermaid, если нет системного Edge/Chrome.",
)
else:
messagebox.showerror(
"md2gost",
"Не удалось скачать Chromium.\n"
"Попробуйте: md2gost --install-chromium\n"
"Или оставьте как есть — Mermaid через QuickJS / kroki.io.",
)
def _pick_into(self, var: tk.StringVar, title: str, types) -> None:
path = filedialog.askopenfilename(title=title, filetypes=types)
if path:
@@ -1300,6 +1369,8 @@ class Md2GostApp:
self.strict_var.set(bool(req.strict))
self.check_pages_var.set(bool(getattr(req, "check_pages", False)))
self.table_repeat_header_var.set(bool(getattr(req, "table_repeat_header", False)))
start = getattr(req, "page_number_start", None)
self.page_start_var.set("" if start is None else str(int(start)))
self.highlight_var.set(bool(req.syntax_highlighting))
self.debug_var.set(bool(req.debug))
self._debug_next = bool(req.debug)
@@ -1333,6 +1404,7 @@ class Md2GostApp:
check_only=self.check_only_var.get(),
check_pages=self.check_pages_var.get(),
table_repeat_header=self.table_repeat_header_var.get(),
page_number_start=self._parse_page_start(),
strict=self.strict_var.get(),
syntax_highlighting=self.highlight_var.get(),
plantuml_jar=self.plantuml_var.get().strip() or None,
@@ -1345,6 +1417,16 @@ class Md2GostApp:
open_when_done=self.open_var.get(),
)
def _parse_page_start(self) -> int | None:
raw = (self.page_start_var.get() or "").strip()
if not raw:
return None
try:
value = int(raw)
except ValueError:
return None
return value if value >= 1 else None
def _parse_diagram_scale(self) -> float:
raw = (self.scale_var.get() or "2").strip().replace(",", ".")
try: