diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c459a24 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/inputs/ +/outputs/ diff --git a/src/__main__.py b/src/__main__.py index 5f874c4..d9b6c2d 100644 --- a/src/__main__.py +++ b/src/__main__.py @@ -38,4 +38,7 @@ def convert( logger.info(f"Будет обработан: {doc_dir.name}") return - process_document(input_dir, output_dir, style_config, template, theme, plugins_dir) \ No newline at end of file + process_document(input_dir, output_dir, style_config, template, theme, plugins_dir) + +if __name__ == "__main__": + app() \ No newline at end of file diff --git a/src/handlers/builtin.py b/src/handlers/builtin.py index e2704df..8d9b4c4 100644 --- a/src/handlers/builtin.py +++ b/src/handlers/builtin.py @@ -58,10 +58,16 @@ def handle_paragraph(node: dict, doc, images_dir: Path, style_reg): @register_handler("image") def handle_image(node: dict, doc, images_dir: Path, style_reg): - src = node["src"] - alt = node.get("alt", "") + # mistune v3: node["attrs"]["url"], alt в children + # старый формат: node["src"], node["alt"] + src = node.get("attrs", {}).get("url") or node.get("src") + # alt: mistune v3 → children[0].raw, старый → node["alt"] + alt_nodes = node.get("children", []) + alt = alt_nodes[0]["raw"] if alt_nodes else node.get("alt", "") + img_path = images_dir / src if img_path.exists(): + logger.debug(f"Обработка изображения: {img_path}, exists: {img_path.exists()}") p = doc.add_paragraph() run = p.add_run() try: @@ -71,16 +77,16 @@ def handle_image(node: dict, doc, images_dir: Path, style_reg): logger.error(f"Ошибка при добавлении изображения {img_path}: {e}") doc.add_paragraph(f"[Изображение не загружено: {src}]") return + if alt: try: cap_p = doc.add_paragraph(alt, style="Caption") except KeyError: cap_p = doc.add_paragraph(alt) style_reg.apply_style(cap_p.style, "Caption") - logger.debug(f"Добавлена подпись без стиля: {alt}") else: doc.add_paragraph(f"[Изображение не найдено: {src}]") - logger.error(f"[Изображение не найдено: {src}]") + logger.warning(f"[Изображение не найдено: {src}]") @register_handler("list") def handle_list(node: dict, doc, images_dir: Path, style_reg): diff --git a/tests/test_gost_example.py b/tests/test_gost_example.py new file mode 100644 index 0000000..ddfcf7b --- /dev/null +++ b/tests/test_gost_example.py @@ -0,0 +1,64 @@ +import pytest +from pathlib import Path +from docx import Document +from src.core.converter import process_document + +@pytest.fixture +def create_gost_example(): + # Создаём inputs/gost_example/ + doc_dir = Path("tests/fixtures/inputs/gost_example") + doc_dir.mkdir(parents=True, exist_ok=True) + + # Создаём document.md + md_content = """ +# ВВЕДЕНИЕ + +Текст введения. + +## 1.1 Актуальность темы + +Текст актуальности. + +| Показатель | 2022 | +|------------|------| +| Выручка | 1000 | + +![Рис. 1 — Диаграмма](images/chart.png) +""" + (doc_dir / "document.md").write_text(md_content, encoding="utf-8") + + # Создаём images/ + (doc_dir / "images").mkdir(exist_ok=True) + + # Создаём изображение + from PIL import Image + img_path = doc_dir / "images/chart.png" + img = Image.new("RGB", (100, 100), color="blue") + img.save(img_path) + + yield doc_dir.parent # возвращаем Path("tests/fixtures/inputs") + + # Удаляем после теста + import shutil + shutil.rmtree(doc_dir.parent, ignore_errors=True) + +def test_gost_example_document_not_empty(create_gost_example): + input_dir = create_gost_example + + process_document( + input_dir=input_dir, + output_dir=Path("tests/output"), + style_config_path=Path("resources/themes/gost.yaml"), + ) + + output_path = Path("tests/output/gost_example.docx") + assert output_path.exists(), "Файл .docx не создан" + + # Открываем и проверяем, что в документе есть хотя бы 1 параграф + doc = Document(output_path) + assert len(doc.paragraphs) > 0, "Документ пустой (нет параграфов)" + assert len(doc.tables) >= 0, "Документ не содержит таблиц (это нормально)" + assert any(p.text.strip() != "" for p in doc.paragraphs), "Все параграфы пустые" + + # Удаляем после теста + output_path.unlink(missing_ok=True) \ No newline at end of file