python-hwpx 2.11.0__py3-none-any.whl → 2.11.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
hwpx/authoring.py CHANGED
@@ -168,16 +168,30 @@ class DocumentStylePreset:
168
168
  heading_bold: bool = True
169
169
  heading_underline: bool = True
170
170
  table_header_bold: bool = True
171
+ title_size: int = 18
172
+ subtitle_size: int = 12
173
+ heading_size: int = 14
174
+ font: str = "함초롬바탕"
171
175
 
172
176
  def ensure_tokens(self, document: HwpxDocument) -> dict[str, str]:
173
177
  """Create/reuse run styles and return semantic token IDs."""
174
178
 
175
179
  return {
176
- "title": document.ensure_run_style(bold=self.title_bold),
177
- "subtitle": document.ensure_run_style(italic=self.subtitle_italic),
180
+ "title": document.ensure_run_style(
181
+ bold=self.title_bold,
182
+ size=self.title_size,
183
+ font=self.font,
184
+ ),
185
+ "subtitle": document.ensure_run_style(
186
+ italic=self.subtitle_italic,
187
+ size=self.subtitle_size,
188
+ font=self.font,
189
+ ),
178
190
  "heading": document.ensure_run_style(
179
191
  bold=self.heading_bold,
180
192
  underline=self.heading_underline,
193
+ size=self.heading_size,
194
+ font=self.font,
181
195
  ),
182
196
  "body": document.ensure_run_style(),
183
197
  "bullet": document.ensure_run_style(),
@@ -186,6 +200,25 @@ class DocumentStylePreset:
186
200
  }
187
201
 
188
202
 
203
+ def _outline_style_refs(document: HwpxDocument, level: int) -> dict[str, str | int]:
204
+ """Return paragraph style refs for a HWP outline heading level, if available."""
205
+
206
+ safe_level = min(10, max(1, int(level)))
207
+ for style in document.styles.values():
208
+ name = str(style.name or "")
209
+ eng_name = str(style.eng_name or "")
210
+ if name == f"개요 {safe_level}" or eng_name == f"Outline {safe_level}":
211
+ refs: dict[str, str | int] = {}
212
+ style_id = style.raw_id if style.raw_id is not None else style.id
213
+ if style_id is None:
214
+ continue
215
+ refs["style_id_ref"] = style_id
216
+ if style.para_pr_id_ref is not None:
217
+ refs["para_pr_id_ref"] = int(style.para_pr_id_ref)
218
+ return refs
219
+ return {}
220
+
221
+
189
222
  def _plan_issue(
190
223
  code: str,
191
224
  path: str,
@@ -1717,6 +1750,7 @@ def _render_block(
1717
1750
  block.text,
1718
1751
  char_pr_id_ref=tokens["heading"],
1719
1752
  inherit_style=False,
1753
+ **_outline_style_refs(document, block.level),
1720
1754
  )
1721
1755
  return
1722
1756
  if isinstance(block, BuilderParagraph):
hwpx/builder/core.py CHANGED
@@ -25,6 +25,25 @@ _A4_HWP_SIZE = (59528, 84188)
25
25
  # changing default node contracts or the plan-v1 authoring style-token path.
26
26
 
27
27
 
28
+ def _outline_style_refs(document: HwpxDocument, level: int) -> dict[str, str | int]:
29
+ """Return paragraph style refs for the built-in HWP outline level, if present."""
30
+
31
+ safe_level = min(10, max(1, int(level)))
32
+ for style in document.styles.values():
33
+ name = str(style.name or "")
34
+ eng_name = str(style.eng_name or "")
35
+ if name == f"개요 {safe_level}" or eng_name == f"Outline {safe_level}":
36
+ refs: dict[str, str | int] = {}
37
+ style_id = style.raw_id if style.raw_id is not None else style.id
38
+ if style_id is None:
39
+ continue
40
+ refs["style_id_ref"] = style_id
41
+ if style.para_pr_id_ref is not None:
42
+ refs["para_pr_id_ref"] = int(style.para_pr_id_ref)
43
+ return refs
44
+ return {}
45
+
46
+
28
47
  @dataclass(frozen=True)
29
48
  class _BuilderPreset:
30
49
  name: str = "default"
@@ -264,6 +283,7 @@ class Heading:
264
283
  section_index=section_index,
265
284
  char_pr_id_ref=char_pr_id,
266
285
  inherit_style=False,
286
+ **_outline_style_refs(document, self.level),
267
287
  )
268
288
 
269
289
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hwpx
3
- Version: 2.11.0
3
+ Version: 2.11.1
4
4
  Summary: 한글 없이 HWPX 문서를 열고, 편집하고, 생성하고, 검증하는 Python 자동화 라이브러리
5
5
  Author: python-hwpx Maintainers
6
6
  License-Expression: Apache-2.0
@@ -261,6 +261,19 @@ HWPX 파일은 **ZIP + XML** 구조이므로, 한/글 프로그램 없이 Python
261
261
  | 🧰 **작업 도구** | unpack/pack/분석/비교 | pack-ready 작업 디렉터리 추출과 재구성 점검 |
262
262
  | 🏗️ **저수준 XML** | 데이터클래스 매핑 | OWPML 스키마 ↔ Python 객체 직접 조작 |
263
263
  | 🔄 **네임스페이스 호환** | 자동 정규화 | HWPML 2016 → 2011 자동 변환 |
264
+ | 🏗️ **빌더** | 조립형 생성 | `hwpx.builder` — Section/Heading/Table/Image/Header 조립, 하드게이트 저장 리포트 |
265
+ | ✅ **편집기 오픈 안전** | `validate_editor_open_safety` | 저장/팩/리페어/빌더 출력 게이트, `openSafety` 증거 반환 |
266
+ | 🧪 **퍼징 수렴 루프** | `hwpx.tools.fuzz` | 시드 결정적 시나리오 생성 · 3중 오라클 러너 · 회귀 fixture 박제 |
267
+ | 🖥️ **레이아웃 프리뷰** | `hwpx.tools.layout_preview` | 페이지 박스·표·여백 근사 HTML/PNG (에이전트 자기검증용) |
268
+ | 🧷 **바이트 보존 패치** | `hwpx.patch` | section XML 바이트 splice — 미수정 영역 바이트 보존 |
269
+ | 📐 **기존 문서 서식 편집** | 문단·페이지 | 정렬·줄간격·들여쓰기·문단 간격, 용지·여백·방향, 머리말/쪽번호, 불릿/번호 |
270
+ | 🖊️ **누름틀** | 양식 필드 | 클릭히어 필드 조회·서식 보존 채움 |
271
+ | 🏛️ **공문서 도구** | `official_lint` · 결재란 | 항목기호 위계·"끝." 표시·붙임·날짜 표기 lint, 결재란 프리셋 |
272
+ | 📷 **고급 생성기** | `advanced_generators` | 사진대지(image_grid)·회의 명패·표 기반 조직도 |
273
+ | 🆚 **신구대조** | `doc_diff` | 문단 LCS diff·신구대조표 생성·참조 정합 lint |
274
+ | 📨 **메일머지·표 계산** | `mail_merge` | 템플릿+데이터 N부 대량 생성, 표 합계·평균 |
275
+ | 🪄 **서식 이식** | `style_profile` | 참조 문서 프로파일 추출·적용, 템플릿 레지스트리 |
276
+ | 🛡️ **입력 강건화** | `opc.security` | XML entity 폭탄·ZIP 압축 폭탄 가드 |
264
277
 
265
278
  ## 기능 상세
266
279
 
@@ -1,5 +1,5 @@
1
1
  hwpx/__init__.py,sha256=W008eCboUXDIsIP6nX4DUB2ihw8oZ8j1NTqF6pA52NY,4833
2
- hwpx/authoring.py,sha256=os6Vue03bMQQ7kL7HsLsezNlH-HXdRkm_jvozfMEo6I,100653
2
+ hwpx/authoring.py,sha256=bO6gwPwM5h-WgV21Cet0bHGzBXf2RxN_ouFpWCdBDuU,101905
3
3
  hwpx/document.py,sha256=faA49Vk6cy5Q9CISELKQcPNbZKvVr_uhewnXuDJpPGY,94836
4
4
  hwpx/form_fill.py,sha256=VUIU53Qa9Ho2aP72biDvJwnDW7ngdAzu3PSd5A7d1JM,9908
5
5
  hwpx/package.py,sha256=0rKjGCJbPQvrVBIy07Jpjsu3fI7HhbqFCGWTiTDsJpo,1141
@@ -8,7 +8,7 @@ hwpx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  hwpx/template_formfit.py,sha256=hlK_t_j5xOAsXlCYvcU_FbqvUyOzSwxitOW_RAqZ3KM,23104
9
9
  hwpx/templates.py,sha256=28bYqeJVeDb1Cq8G9NZG9Mhnu4K2GamAKC4QhxvUZyA,1187
10
10
  hwpx/builder/__init__.py,sha256=a_-rN6GeQjWYRNdNDRGKKc3q98lSjpqmxe3wAfSfiMo,736
11
- hwpx/builder/core.py,sha256=HwdP2smNv9dJ-LUdsqoihIHNJ3nJAMCn-9Z23X5PCyg,26945
11
+ hwpx/builder/core.py,sha256=SlW9GJ_2PjpyfHvILJSynGUUtsC1DDtN2LRdCAVwry0,27806
12
12
  hwpx/builder/report.py,sha256=NZ4Dgtk-KBb_seaxVzwcTqaDvD20cK0zsnXnKRR_X1M,4389
13
13
  hwpx/data/Skeleton.hwpx,sha256=K0EdMIs33s1dTTWMd-pE1ZQGChFkBcJvJh6OPqk078w,7474
14
14
  hwpx/opc/package.py,sha256=ORBWLwVb0_i8xEuj0IM3BJ_1Xh349zj1U0MCiaCHx1M,35136
@@ -71,10 +71,10 @@ hwpx/tools/fuzz/catalog.py,sha256=Cdc8qKeYy32cDMC6ULqAnlxv8BIlY83ZBe7xFCiiUQs,10
71
71
  hwpx/tools/fuzz/generator.py,sha256=G2tGmo4-i-i0v_-rqHsNKZjfpD5wAJZRMsLTPu_KZfg,7381
72
72
  hwpx/tools/fuzz/minimize.py,sha256=gv9fEU1PsmpXR-Z6wiejMC0umHV90GYhtO2Ht8x2__Y,1055
73
73
  hwpx/tools/fuzz/runner.py,sha256=NkSrlWUf813SqEwkhi05LmusMgM9r2j2JiPCqzzvPN8,17906
74
- python_hwpx-2.11.0.dist-info/licenses/LICENSE,sha256=_ubz4wv-BkkT3l3gu-QuH7JGeVjuRYGZoZK95eNsCHU,9688
75
- python_hwpx-2.11.0.dist-info/licenses/NOTICE,sha256=k48h6EaGQE8Y1c0dS9sIOOcz4YqkbcImWClF7pBOgsg,2473
76
- python_hwpx-2.11.0.dist-info/METADATA,sha256=Hkkb8-mjomEetIqlH3hhIoQ56HQZT3gycg7gEIotb0Q,18099
77
- python_hwpx-2.11.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
78
- python_hwpx-2.11.0.dist-info/entry_points.txt,sha256=JUKRxbly9UaeHV7YzOea23y8IiqSTcrhUlooP3fS_Zc,405
79
- python_hwpx-2.11.0.dist-info/top_level.txt,sha256=R1iToqDh80Nf2oQhRjTN0rbN2X6kyDUizIocZjkhuxc,5
80
- python_hwpx-2.11.0.dist-info/RECORD,,
74
+ python_hwpx-2.11.1.dist-info/licenses/LICENSE,sha256=_ubz4wv-BkkT3l3gu-QuH7JGeVjuRYGZoZK95eNsCHU,9688
75
+ python_hwpx-2.11.1.dist-info/licenses/NOTICE,sha256=k48h6EaGQE8Y1c0dS9sIOOcz4YqkbcImWClF7pBOgsg,2473
76
+ python_hwpx-2.11.1.dist-info/METADATA,sha256=pPik6X8lpzmXwiihcdLUATJjFWczhSdQh44HncE1ay4,19751
77
+ python_hwpx-2.11.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
78
+ python_hwpx-2.11.1.dist-info/entry_points.txt,sha256=JUKRxbly9UaeHV7YzOea23y8IiqSTcrhUlooP3fS_Zc,405
79
+ python_hwpx-2.11.1.dist-info/top_level.txt,sha256=R1iToqDh80Nf2oQhRjTN0rbN2X6kyDUizIocZjkhuxc,5
80
+ python_hwpx-2.11.1.dist-info/RECORD,,