[AI]
ГОСТ
This commit is contained in:
@@ -67,4 +67,4 @@ styles:
|
||||
line_spacing: 1.0
|
||||
|
||||
colors:
|
||||
LinkColor: "0000FF"
|
||||
LinkColor: "000"
|
||||
@@ -14,6 +14,13 @@ def process_document(
|
||||
template_path: Optional[Path] = None, theme_name: Optional[str] = None,
|
||||
plugins_dir: Optional[Path] = None, dry_run: bool = False
|
||||
):
|
||||
if theme_name:
|
||||
theme_path = Path("resources/themes") / f"{theme_name}.yaml"
|
||||
if theme_path.exists():
|
||||
style_config_path = theme_path
|
||||
else:
|
||||
logger.warning(f"Тема {theme_name} не найдена, используем стандартный стиль")
|
||||
|
||||
if plugins_dir and plugins_dir.exists():
|
||||
load_plugins_from_path(plugins_dir)
|
||||
|
||||
@@ -42,6 +49,7 @@ def process_document(
|
||||
|
||||
style_reg = StyleRegistry(style_config_path)
|
||||
style_reg.ensure_styles_in_doc(doc)
|
||||
style_reg.apply_page_layout(doc) # ✅ применяем поля
|
||||
render_markdown_to_docx(doc, md_content, images_dir, style_reg)
|
||||
|
||||
output_path = output_dir / f"{doc_name}.docx"
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import yaml
|
||||
from docx import Document
|
||||
from docx.enum.style import WD_STYLE_TYPE
|
||||
from docx.shared import Pt, RGBColor
|
||||
from docx.shared import Pt, Cm, RGBColor
|
||||
from docx.enum.text import WD_LINE_SPACING, WD_ALIGN_PARAGRAPH
|
||||
from docx.styles.style import ParagraphStyle
|
||||
|
||||
class StyleRegistry:
|
||||
def __init__(self, config_path):
|
||||
@@ -20,6 +19,24 @@ class StyleRegistry:
|
||||
style = doc.styles.add_style(name, WD_STYLE_TYPE.PARAGRAPH)
|
||||
self.apply_style(style, name)
|
||||
|
||||
def apply_page_layout(self, doc: Document):
|
||||
"""Применяет настройки страницы (поля)."""
|
||||
page_cfg = self.config.get("page", {})
|
||||
margins = page_cfg.get("margins", {})
|
||||
if not margins:
|
||||
return
|
||||
|
||||
sections = doc.sections
|
||||
for section in sections:
|
||||
if "top" in margins:
|
||||
section.top_margin = Cm(margins["top"])
|
||||
if "bottom" in margins:
|
||||
section.bottom_margin = Cm(margins["bottom"])
|
||||
if "left" in margins:
|
||||
section.left_margin = Cm(margins["left"])
|
||||
if "right" in margins:
|
||||
section.right_margin = Cm(margins["right"])
|
||||
|
||||
def apply_style(self, style, style_name: str):
|
||||
cfg = self.config["styles"].get(style_name)
|
||||
if not cfg:
|
||||
@@ -50,6 +67,9 @@ class StyleRegistry:
|
||||
align = alignment_map.get(para_cfg["alignment"])
|
||||
if align:
|
||||
pf.alignment = align
|
||||
if "first_line_indent" in para_cfg:
|
||||
from docx.shared import Mm
|
||||
pf.first_line_indent = Mm(para_cfg["first_line_indent"])
|
||||
|
||||
def get_color(self, key: str):
|
||||
hex_color = self.config.get("colors", {}).get(key, "000000")
|
||||
|
||||
145
tests/test_page_layout.py
Normal file
145
tests/test_page_layout.py
Normal file
@@ -0,0 +1,145 @@
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from docx import Document
|
||||
from src.core.style_registry import StyleRegistry
|
||||
|
||||
def test_apply_page_layout_all_margins():
|
||||
"""Тест: все поля заданы."""
|
||||
yaml_content = """
|
||||
page:
|
||||
margins:
|
||||
top: 2.0
|
||||
bottom: 2.0
|
||||
left: 3.0
|
||||
right: 1.0
|
||||
styles:
|
||||
Normal:
|
||||
font:
|
||||
name: "Arial"
|
||||
size: 12
|
||||
"""
|
||||
yaml_path = Path("tests/fixtures/test_layout_all.yaml")
|
||||
yaml_path.parent.mkdir(exist_ok=True)
|
||||
yaml_path.write_text(yaml_content, encoding="utf-8")
|
||||
|
||||
doc = Document()
|
||||
style_reg = StyleRegistry(yaml_path)
|
||||
style_reg.apply_page_layout(doc)
|
||||
|
||||
section = doc.sections[0]
|
||||
assert abs(section.top_margin.cm - 2.0) < 0.01
|
||||
assert abs(section.bottom_margin.cm - 2.0) < 0.01
|
||||
assert abs(section.left_margin.cm - 3.0) < 0.01
|
||||
assert abs(section.right_margin.cm - 1.0) < 0.01
|
||||
|
||||
yaml_path.unlink(missing_ok=True)
|
||||
|
||||
def test_apply_page_layout_partial_margins():
|
||||
"""Тест: заданы не все поля."""
|
||||
yaml_content = """
|
||||
page:
|
||||
margins:
|
||||
top: 1.5
|
||||
left: 2.5
|
||||
styles:
|
||||
Normal:
|
||||
font:
|
||||
name: "Arial"
|
||||
size: 12
|
||||
"""
|
||||
yaml_path = Path("tests/fixtures/test_layout_partial.yaml")
|
||||
yaml_path.parent.mkdir(exist_ok=True)
|
||||
yaml_path.write_text(yaml_content, encoding="utf-8")
|
||||
|
||||
doc = Document()
|
||||
style_reg = StyleRegistry(yaml_path)
|
||||
style_reg.apply_page_layout(doc)
|
||||
|
||||
section = doc.sections[0]
|
||||
assert abs(section.top_margin.cm - 1.5) < 0.01
|
||||
assert abs(section.left_margin.cm - 2.5) < 0.01
|
||||
# Остальные поля не должны измениться (остаются по умолчанию)
|
||||
# У docx по умолчанию: top=2.54, bottom=2.54, left=3.17, right=3.17
|
||||
# Но мы их не трогаем, если в YAML нет
|
||||
|
||||
yaml_path.unlink(missing_ok=True)
|
||||
|
||||
def test_apply_page_layout_no_page_section():
|
||||
"""Тест: в YAML нет секции page."""
|
||||
yaml_content = """
|
||||
styles:
|
||||
Normal:
|
||||
font:
|
||||
name: "Arial"
|
||||
size: 12
|
||||
"""
|
||||
yaml_path = Path("tests/fixtures/test_layout_no_page.yaml")
|
||||
yaml_path.parent.mkdir(exist_ok=True)
|
||||
yaml_path.write_text(yaml_content, encoding="utf-8")
|
||||
|
||||
doc = Document()
|
||||
style_reg = StyleRegistry(yaml_path)
|
||||
style_reg.apply_page_layout(doc)
|
||||
|
||||
section = doc.sections[0]
|
||||
# Поля не должны измениться (остаются по умолчанию)
|
||||
# top=2.54 cm по умолчанию
|
||||
assert abs(section.top_margin.cm - 2.54) < 0.01
|
||||
|
||||
yaml_path.unlink(missing_ok=True)
|
||||
|
||||
def test_apply_page_layout_no_margins():
|
||||
"""Тест: в YAML есть page, но нет margins."""
|
||||
yaml_content = """
|
||||
page:
|
||||
other_option: value
|
||||
styles:
|
||||
Normal:
|
||||
font:
|
||||
name: "Arial"
|
||||
size: 12
|
||||
"""
|
||||
yaml_path = Path("tests/fixtures/test_layout_no_margins.yaml")
|
||||
yaml_path.parent.mkdir(exist_ok=True)
|
||||
yaml_path.write_text(yaml_content, encoding="utf-8")
|
||||
|
||||
doc = Document()
|
||||
style_reg = StyleRegistry(yaml_path)
|
||||
style_reg.apply_page_layout(doc)
|
||||
|
||||
section = doc.sections[0]
|
||||
# Поля не должны измениться
|
||||
assert abs(section.top_margin.cm - 2.54) < 0.01
|
||||
|
||||
yaml_path.unlink(missing_ok=True)
|
||||
|
||||
def test_apply_page_layout_zero_margins():
|
||||
"""Тест: нулевые поля."""
|
||||
yaml_content = """
|
||||
page:
|
||||
margins:
|
||||
top: 0.0
|
||||
bottom: 0.0
|
||||
left: 0.0
|
||||
right: 0.0
|
||||
styles:
|
||||
Normal:
|
||||
font:
|
||||
name: "Arial"
|
||||
size: 12
|
||||
"""
|
||||
yaml_path = Path("tests/fixtures/test_layout_zero.yaml")
|
||||
yaml_path.parent.mkdir(exist_ok=True)
|
||||
yaml_path.write_text(yaml_content, encoding="utf-8")
|
||||
|
||||
doc = Document()
|
||||
style_reg = StyleRegistry(yaml_path)
|
||||
style_reg.apply_page_layout(doc)
|
||||
|
||||
section = doc.sections[0]
|
||||
assert abs(section.top_margin.cm - 0.0) < 0.01
|
||||
assert abs(section.bottom_margin.cm - 0.0) < 0.01
|
||||
assert abs(section.left_margin.cm - 0.0) < 0.01
|
||||
assert abs(section.right_margin.cm - 0.0) < 0.01
|
||||
|
||||
yaml_path.unlink(missing_ok=True)
|
||||
Reference in New Issue
Block a user