diff --git a/CHANGELOG.md b/CHANGELOG.md index 45347ef9..f6a008e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -135,6 +135,9 @@ 픽셀(96dpi, 75 HWPUNIT) 단위로 올려 세고(반경 400은 450), 뻗는 길이는 HWPUNIT 아래를 버린다. 반사는 대략 그 몫만큼의 그림(빛남 포함) 높이와 거리만큼 아래로 자리를 차지한다(한/글과 한 픽셀 안팎 차이). 부드러운 가장자리는 자리를 차지하지 않는다. +- `add_section()`이 만든 구역은 메모리에서도 한/글의 이름공간 접두사(`hs:sec`, `hp:p` 등)를 쓴다. 전에는 `ns0:sec`, + `ns4:p`처럼 붙어(저장할 때는 바로잡혔다), 그 구역에 넣은 표의 셀 나누기 같은 구조 편집이 `TableStructureError`로 멈췄다. + 그 오류 문구도 바로잡았다. - 쪽 수 추정이 문단 맨 위에 둔 위아래 배치 표 아래로 문단 첫 줄이 그 쪽에 들어가지 않을 때 한/글처럼 놓는다. 그 쪽에서 끝나는 표는 첫 줄과 함께 다음 쪽 맨 위로 간다. 행 단위로 나누는 표는 그 쪽에 다 들어갈 때, 셀 단위로 나누는 표는 마지막 행의 남는 높이를 잘라 그 쪽에서 끝날 때도 그렇다. 나누지 않는 표가 그 자리에 들어가지 않으면 diff --git a/src/hwpx/oxml/document_parts.py b/src/hwpx/oxml/document_parts.py index fb447147..5940db01 100644 --- a/src/hwpx/oxml/document_parts.py +++ b/src/hwpx/oxml/document_parts.py @@ -6,7 +6,7 @@ from copy import deepcopy from dataclasses import dataclass import logging -from typing import TYPE_CHECKING, Any, Callable, Iterable, Mapping, Sequence, TypeVar +from typing import TYPE_CHECKING, Any, Callable, Iterable, Mapping, Sequence, TypeVar, cast import xml.etree.ElementTree as ET from hwpx.opc.relationships import resolve_part_name @@ -1293,7 +1293,11 @@ def add_section(self, *, after: int | None = None) -> HwpxOxmlSection: # Build a renderable empty section. ``secPr`` and ``colPr`` must # precede body text in the first paragraph's first run. - section_element = section_properties.makeelement(f"{_HS}sec", {}) + # with the namespace prefixes Hancom writes (hs, hp, hc, ...): structure edits read the hp prefix + from .namespaces import HWPML_COMPAT_ROOT_NAMESPACES + + section_element = cast(Any, section_properties).makeelement( + f"{_HS}sec", {}, nsmap=HWPML_COMPAT_ROOT_NAMESPACES) para_attrs = {"id": _paragraph_id(), **_DEFAULT_PARAGRAPH_ATTRS} para = _append_child(section_element, f"{_HP}p", para_attrs) run = _append_child(para, f"{_HP}run", {"charPrIDRef": "0"}) diff --git a/src/hwpx/oxml/table_structure.py b/src/hwpx/oxml/table_structure.py index 899486cc..b8f9bee4 100644 --- a/src/hwpx/oxml/table_structure.py +++ b/src/hwpx/oxml/table_structure.py @@ -117,7 +117,7 @@ def _restructure(self, op: dict[str, Any]) -> None: element = self.element if element.prefix != "hp": - raise TableStructureError("structure edits read a table whose paragraph namespace is prefixed hp") + raise TableStructureError("structure edits need a table whose paragraph namespace is prefixed hp") section = self.paragraph.section sections = section.document.sections if section.document is not None else [section] used = { diff --git a/tests/test_paragraph_section_management.py b/tests/test_paragraph_section_management.py index 55df6b95..96340fb2 100644 --- a/tests/test_paragraph_section_management.py +++ b/tests/test_paragraph_section_management.py @@ -183,6 +183,17 @@ def test_add_section_appends(self): "t", ] + def test_add_section_writes_the_documents_namespace_prefixes(self): + # The new section's XML takes the prefixes of the document's sections (hs:sec, hp:p, ...), so a + # table added there can take structure edits like any other. + doc = _new() + new_section = doc.add_section() + table = doc.add_table(3, 3, section=new_section) + + assert (new_section.element.prefix, table.element.prefix) == ("hs", "hp") + table.split_cell(2, 2, rows=1, cols=2) + assert table.column_count >= 3 + def test_add_section_after(self, tmp_path): doc = _new() second = doc.add_section()