python-hwpx 2.24.0__tar.gz → 2.24.1__tar.gz

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.
Files changed (291) hide show
  1. {python_hwpx-2.24.0/src/python_hwpx.egg-info → python_hwpx-2.24.1}/PKG-INFO +11 -2
  2. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/README.md +9 -0
  3. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/pyproject.toml +15 -2
  4. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/_document_impl.py +11 -2
  5. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/table_patch.py +30 -0
  6. {python_hwpx-2.24.0 → python_hwpx-2.24.1/src/python_hwpx.egg-info}/PKG-INFO +11 -2
  7. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/python_hwpx.egg-info/requires.txt +1 -1
  8. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_document_formatting.py +22 -0
  9. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_table_patch.py +42 -0
  10. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/LICENSE +0 -0
  11. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/NOTICE +0 -0
  12. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/setup.cfg +0 -0
  13. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/__init__.py +0 -0
  14. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/authoring.py +0 -0
  15. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/body_patch.py +0 -0
  16. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/builder/__init__.py +0 -0
  17. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/builder/core.py +0 -0
  18. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/builder/report.py +0 -0
  19. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/__init__.py +0 -0
  20. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/badges.py +0 -0
  21. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/corpus/corpus.json +0 -0
  22. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/corpus/meeting_summary.hwpx +0 -0
  23. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/corpus/notice.hwpx +0 -0
  24. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/corpus/report_table.hwpx +0 -0
  25. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/corpus.py +0 -0
  26. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/report.py +0 -0
  27. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/roundtrip_batch.py +0 -0
  28. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/conformance/runner.py +0 -0
  29. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/data/Skeleton.hwpx +0 -0
  30. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/__init__.py +0 -0
  31. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/_support.py +0 -0
  32. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/composer.py +0 -0
  33. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/harvest.py +0 -0
  34. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/plan.py +0 -0
  35. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profile.py +0 -0
  36. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/application_form/fragments/body.xml +0 -0
  37. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/application_form/fragments/heading.xml +0 -0
  38. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/application_form/fragments/info_table.xml +0 -0
  39. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/application_form/fragments/title.xml +0 -0
  40. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/application_form/profile.json +0 -0
  41. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/application_form/template.hwpx +0 -0
  42. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/home_notice/fragments/body.xml +0 -0
  43. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/home_notice/fragments/heading.xml +0 -0
  44. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/home_notice/fragments/title.xml +0 -0
  45. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/home_notice/profile.json +0 -0
  46. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/home_notice/template.hwpx +0 -0
  47. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/official_notice/fragments/body.xml +0 -0
  48. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/official_notice/fragments/heading.xml +0 -0
  49. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/official_notice/fragments/info_table.xml +0 -0
  50. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/official_notice/fragments/title.xml +0 -0
  51. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/official_notice/profile.json +0 -0
  52. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/official_notice/template.hwpx +0 -0
  53. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/report/fragments/body.xml +0 -0
  54. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/report/fragments/heading.xml +0 -0
  55. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/report/fragments/info_table.xml +0 -0
  56. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/report/fragments/title.xml +0 -0
  57. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/report/profile.json +0 -0
  58. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/profiles/report/template.hwpx +0 -0
  59. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/design/validator.py +0 -0
  60. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/document.py +0 -0
  61. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/evalplan_fill.py +0 -0
  62. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/exam/__init__.py +0 -0
  63. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/exam/compose.py +0 -0
  64. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/exam/ir.py +0 -0
  65. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/exam/measure.py +0 -0
  66. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/exam/parser.py +0 -0
  67. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/exam/profile.py +0 -0
  68. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/fill_residue.py +0 -0
  69. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fill.py +0 -0
  70. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/__init__.py +0 -0
  71. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/apply.py +0 -0
  72. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/engine.py +0 -0
  73. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/measure.py +0 -0
  74. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/policy.py +0 -0
  75. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/report.py +0 -0
  76. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/seal.py +0 -0
  77. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/form_fit/wordbox.py +0 -0
  78. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/formfill_quality.py +0 -0
  79. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/guidance_scan.py +0 -0
  80. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/ingest/__init__.py +0 -0
  81. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/ingest/base.py +0 -0
  82. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/ingest/hwpx_converter.py +0 -0
  83. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/layout/__init__.py +0 -0
  84. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/layout/lint.py +0 -0
  85. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/layout/report.py +0 -0
  86. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/opc/package.py +0 -0
  87. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/opc/relationships.py +0 -0
  88. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/opc/security.py +0 -0
  89. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/opc/xml_utils.py +0 -0
  90. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/__init__.py +0 -0
  91. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/body.py +0 -0
  92. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/canonical_defaults.py +0 -0
  93. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/common.py +0 -0
  94. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/document.py +0 -0
  95. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/header.py +0 -0
  96. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/header_part.py +0 -0
  97. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/memo.py +0 -0
  98. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/namespaces.py +0 -0
  99. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/numbering.py +0 -0
  100. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/objects.py +0 -0
  101. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/paragraph.py +0 -0
  102. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/parser.py +0 -0
  103. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/run.py +0 -0
  104. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/schema.py +0 -0
  105. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/section.py +0 -0
  106. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/simple_parts.py +0 -0
  107. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/table.py +0 -0
  108. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/oxml/utils.py +0 -0
  109. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/package.py +0 -0
  110. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/patch.py +0 -0
  111. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/presets/__init__.py +0 -0
  112. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/presets/proposal.py +0 -0
  113. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/py.typed +0 -0
  114. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/quality/__init__.py +0 -0
  115. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/quality/ledger.py +0 -0
  116. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/quality/policy.py +0 -0
  117. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/quality/report.py +0 -0
  118. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/quality/save_pipeline.py +0 -0
  119. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/template_formfit.py +0 -0
  120. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/templates.py +0 -0
  121. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/__init__.py +0 -0
  122. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/_schemas/header.xsd +0 -0
  123. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/_schemas/section.xsd +0 -0
  124. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/advanced_generators.py +0 -0
  125. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/archive_cli.py +0 -0
  126. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/doc_diff.py +0 -0
  127. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/exporter.py +0 -0
  128. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/fuzz/__init__.py +0 -0
  129. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/fuzz/__main__.py +0 -0
  130. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/fuzz/catalog.py +0 -0
  131. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/fuzz/generator.py +0 -0
  132. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/fuzz/minimize.py +0 -0
  133. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/fuzz/runner.py +0 -0
  134. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/generic_inventory.py +0 -0
  135. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/id_integrity.py +0 -0
  136. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/idempotence.py +0 -0
  137. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/ir_equality.py +0 -0
  138. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/layout_preview.py +0 -0
  139. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/mail_merge.py +0 -0
  140. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/markdown_export.py +0 -0
  141. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/object_finder.py +0 -0
  142. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/official_lint.py +0 -0
  143. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/package_reconcile.py +0 -0
  144. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/package_validator.py +0 -0
  145. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/page_guard.py +0 -0
  146. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/pii.py +0 -0
  147. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/read_fidelity.py +0 -0
  148. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/recover.py +0 -0
  149. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/redline.py +0 -0
  150. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/repair.py +0 -0
  151. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/report_parser.py +0 -0
  152. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/report_utils.py +0 -0
  153. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/roundtrip_diff.py +0 -0
  154. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/style_profile.py +0 -0
  155. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/table_cleanup.py +0 -0
  156. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/table_compute.py +0 -0
  157. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/table_navigation.py +0 -0
  158. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/template_analyzer.py +0 -0
  159. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/text_extract_cli.py +0 -0
  160. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/text_extractor.py +0 -0
  161. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/toc_author.py +0 -0
  162. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/toc_fidelity.py +0 -0
  163. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/tools/validator.py +0 -0
  164. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/__init__.py +0 -0
  165. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/_hancom_open_rate.ps1 +0 -0
  166. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/_refresh_hwpx_mac.applescript +0 -0
  167. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/_render_hwpx.ps1 +0 -0
  168. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/_render_hwpx_mac.applescript +0 -0
  169. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/detectors.py +0 -0
  170. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/diff.py +0 -0
  171. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/masks.py +0 -0
  172. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/oracle.py +0 -0
  173. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/hwpx/visual/report.py +0 -0
  174. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/python_hwpx.egg-info/SOURCES.txt +0 -0
  175. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/python_hwpx.egg-info/dependency_links.txt +0 -0
  176. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/python_hwpx.egg-info/entry_points.txt +0 -0
  177. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/src/python_hwpx.egg-info/top_level.txt +0 -0
  178. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_advanced_generators.py +0 -0
  179. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_authoring_profile_routing.py +0 -0
  180. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_authoring_profile_routing_oracle.py +0 -0
  181. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_authoring_render_check.py +0 -0
  182. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_body_patch.py +0 -0
  183. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_builder_core.py +0 -0
  184. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_builder_plan_v2.py +0 -0
  185. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_builder_vertical_slice.py +0 -0
  186. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_cell_line_spacing.py +0 -0
  187. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_comment_node_robustness.py +0 -0
  188. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_conformance.py +0 -0
  189. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_corpus_read_fidelity.py +0 -0
  190. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_coverage_promotion.py +0 -0
  191. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_coverage_targets.py +0 -0
  192. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_design_builder.py +0 -0
  193. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_deviations_registry.py +0 -0
  194. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_doc_diff.py +0 -0
  195. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_document_context_manager.py +0 -0
  196. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_document_plan.py +0 -0
  197. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_document_plan_computed_fields.py +0 -0
  198. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_document_save_api.py +0 -0
  199. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_evalplan_fill.py +0 -0
  200. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_exam_compose.py +0 -0
  201. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_exam_compose_oracle.py +0 -0
  202. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_exam_fixtures.py +0 -0
  203. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_exam_ir.py +0 -0
  204. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_exam_measure.py +0 -0
  205. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_exam_parser.py +0 -0
  206. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_exam_profile.py +0 -0
  207. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_existing_document_format_editing.py +0 -0
  208. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_fill_residue.py +0 -0
  209. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_form_fields.py +0 -0
  210. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_form_fill_split_run.py +0 -0
  211. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_form_fit.py +0 -0
  212. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_form_fit_integration.py +0 -0
  213. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_form_fit_seal.py +0 -0
  214. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_form_fit_seal_placement.py +0 -0
  215. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_form_fit_wordbox.py +0 -0
  216. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_formfill_quality.py +0 -0
  217. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_fuzz_loop.py +0 -0
  218. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_fuzz_regressions.py +0 -0
  219. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_gap_closure_tools.py +0 -0
  220. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_government_report_preset.py +0 -0
  221. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_government_table_profile.py +0 -0
  222. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_guidance_scan.py +0 -0
  223. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_hp_tab_support.py +0 -0
  224. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_hwpxlib_corpus_read.py +0 -0
  225. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_id_generator_range.py +0 -0
  226. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_id_integrity.py +0 -0
  227. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_image_object_workflow.py +0 -0
  228. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_ingest.py +0 -0
  229. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_inline_models.py +0 -0
  230. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_integration_hwpx_compatibility.py +0 -0
  231. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_integration_roundtrip.py +0 -0
  232. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_kordoc_absorption.py +0 -0
  233. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_layout_lint.py +0 -0
  234. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_layout_preview.py +0 -0
  235. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_mail_merge_fit.py +0 -0
  236. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_mail_merge_table_compute.py +0 -0
  237. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_mail_merge_xlsx.py +0 -0
  238. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_markdown_export.py +0 -0
  239. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_memo_and_style_editing.py +0 -0
  240. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_namespace_handling.py +0 -0
  241. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_new_features.py +0 -0
  242. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_official_document_style.py +0 -0
  243. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_official_lint_gongmun_gate.py +0 -0
  244. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_official_lint_tableaware.py +0 -0
  245. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_opc_package.py +0 -0
  246. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_open_safety_corpus.py +0 -0
  247. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_openrate.py +0 -0
  248. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_oxml_parsing.py +0 -0
  249. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_packaging_license_metadata.py +0 -0
  250. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_packaging_py_typed.py +0 -0
  251. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_paragraph_keep_together.py +0 -0
  252. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_paragraph_section_management.py +0 -0
  253. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_pii.py +0 -0
  254. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_pii_structural.py +0 -0
  255. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_pii_wiring.py +0 -0
  256. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_proposal_preset.py +0 -0
  257. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_question_split_detector.py +0 -0
  258. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_read_fidelity.py +0 -0
  259. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_recover_broken_zip.py +0 -0
  260. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_redline_authoring.py +0 -0
  261. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_redline_verify.py +0 -0
  262. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_repair_repack.py +0 -0
  263. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_report_parser.py +0 -0
  264. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_report_utils.py +0 -0
  265. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_repr_snapshots.py +0 -0
  266. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_rhwp_t1_gates.py +0 -0
  267. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_rhwp_t2_verification.py +0 -0
  268. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_roundtrip_fidelity.py +0 -0
  269. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_row_heights.py +0 -0
  270. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_save_pipeline.py +0 -0
  271. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_save_pipeline_no_bypass.py +0 -0
  272. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_section_headers.py +0 -0
  273. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_set_paragraph_format_keep.py +0 -0
  274. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_skeleton_template_ids.py +0 -0
  275. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_split_cell.py +0 -0
  276. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_split_merged_cell.py +0 -0
  277. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_style_profile.py +0 -0
  278. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_table_cleanup.py +0 -0
  279. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_table_navigation.py +0 -0
  280. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_table_patch_dryrun.py +0 -0
  281. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_table_patch_m105.py +0 -0
  282. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_tables_default_border.py +0 -0
  283. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_template_analyzer_enrichment.py +0 -0
  284. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_template_formfit.py +0 -0
  285. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_text_extractor_annotations.py +0 -0
  286. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_toc_author.py +0 -0
  287. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_toc_fidelity.py +0 -0
  288. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_validation_severity.py +0 -0
  289. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_validator_comment_nodes.py +0 -0
  290. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_version_metadata.py +0 -0
  291. {python_hwpx-2.24.0 → python_hwpx-2.24.1}/tests/test_visual_oracle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hwpx
3
- Version: 2.24.0
3
+ Version: 2.24.1
4
4
  Summary: 한글 없이 HWPX 문서를 열고, 편집하고, 생성하고, 검증하는 Python 자동화 라이브러리
5
5
  Author: python-hwpx Maintainers
6
6
  License-Expression: Apache-2.0
@@ -20,7 +20,7 @@ Requires-Python: >=3.10
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  License-File: NOTICE
23
- Requires-Dist: lxml<6,>=4.9
23
+ Requires-Dist: lxml<7,>=4.9
24
24
  Provides-Extra: visual
25
25
  Requires-Dist: pymupdf>=1.24; extra == "visual"
26
26
  Requires-Dist: pillow>=10.0; extra == "visual"
@@ -202,6 +202,15 @@ pip install -e ".[dev]"
202
202
  pytest
203
203
  ```
204
204
 
205
+ ## 감사의 말
206
+
207
+ 아래 공개 표준·프로젝트에 빚지고 있습니다.
208
+
209
+ - **[OWPML — 개방형 워드프로세서 마크업 언어 (KS X 6101)](https://www.kssn.net/search/stddetail.do?itemNo=K001010119985)** — HWPX가 기반하는 한국 산업 표준
210
+ - **[hancom-io/hwpx-owpml-model](https://github.com/hancom-io/hwpx-owpml-model)** — OWPML 요소 구조 참조 모델 · **[neolord0/hwpxlib](https://github.com/neolord0/hwpxlib)** — 오라클 샘플 코퍼스
211
+ - **[edwardkim/rhwp](https://github.com/edwardkim/rhwp)** — 멱등성·검증 게이트 설계 영감
212
+ - **범정부오피스** — 공무 문서 편집 워크플로 아이디어
213
+
205
214
  ## License
206
215
 
207
216
  Apache License 2.0. See LICENSE and NOTICE.
@@ -160,6 +160,15 @@ pip install -e ".[dev]"
160
160
  pytest
161
161
  ```
162
162
 
163
+ ## 감사의 말
164
+
165
+ 아래 공개 표준·프로젝트에 빚지고 있습니다.
166
+
167
+ - **[OWPML — 개방형 워드프로세서 마크업 언어 (KS X 6101)](https://www.kssn.net/search/stddetail.do?itemNo=K001010119985)** — HWPX가 기반하는 한국 산업 표준
168
+ - **[hancom-io/hwpx-owpml-model](https://github.com/hancom-io/hwpx-owpml-model)** — OWPML 요소 구조 참조 모델 · **[neolord0/hwpxlib](https://github.com/neolord0/hwpxlib)** — 오라클 샘플 코퍼스
169
+ - **[edwardkim/rhwp](https://github.com/edwardkim/rhwp)** — 멱등성·검증 게이트 설계 영감
170
+ - **범정부오피스** — 공무 문서 편집 워크플로 아이디어
171
+
163
172
  ## License
164
173
 
165
174
  Apache License 2.0. See LICENSE and NOTICE.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-hwpx"
7
- version = "2.24.0"
7
+ version = "2.24.1"
8
8
  description = "한글 없이 HWPX 문서를 열고, 편집하고, 생성하고, 검증하는 Python 자동화 라이브러리"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  license = "Apache-2.0"
@@ -25,7 +25,7 @@ classifiers = [
25
25
  "Topic :: Text Processing :: Markup :: XML",
26
26
  ]
27
27
  dependencies = [
28
- "lxml>=4.9,<6",
28
+ "lxml>=4.9,<7",
29
29
  ]
30
30
 
31
31
  [project.optional-dependencies]
@@ -100,11 +100,19 @@ testpaths = ["tests"]
100
100
 
101
101
  [tool.mypy]
102
102
  python_version = "3.10"
103
+ # Explicit gradual-migration allowlist: transitive imports enter the gate only
104
+ # after they are added here and made clean themselves.
105
+ follow_imports = "skip"
103
106
  files = [
104
107
  "src/hwpx/document.py",
105
108
  "src/hwpx/oxml/document.py",
106
109
  "src/hwpx/opc/package.py",
107
110
  "src/hwpx/opc/relationships.py",
111
+ "src/hwpx/oxml/paragraph.py",
112
+ "src/hwpx/oxml/run.py",
113
+ "src/hwpx/oxml/table.py",
114
+ "src/hwpx/quality/policy.py",
115
+ "src/hwpx/quality/report.py",
108
116
  "src/hwpx/tools/archive_cli.py",
109
117
  "src/hwpx/tools/package_validator.py",
110
118
  "src/hwpx/tools/page_guard.py",
@@ -126,6 +134,11 @@ ignore_errors = true
126
134
  include = [
127
135
  "src/hwpx/opc/package.py",
128
136
  "src/hwpx/opc/relationships.py",
137
+ "src/hwpx/oxml/paragraph.py",
138
+ "src/hwpx/oxml/run.py",
139
+ "src/hwpx/oxml/table.py",
140
+ "src/hwpx/quality/policy.py",
141
+ "src/hwpx/quality/report.py",
129
142
  "src/hwpx/tools/archive_cli.py",
130
143
  "src/hwpx/tools/package_validator.py",
131
144
  "src/hwpx/tools/page_guard.py",
@@ -2796,14 +2796,23 @@ class HwpxOxmlTableCell:
2796
2796
  preserve_format: bool = True,
2797
2797
  split_paragraphs: bool = False,
2798
2798
  ) -> None:
2799
+ previous_text = self.text
2800
+ sanitized_value = _sanitize_text(value)
2801
+ if sanitized_value and sanitized_value != previous_text:
2802
+ sublist = self._ensure_sublist()
2803
+ if (sublist.get("lineWrap") or "").upper() == "SQUEEZE":
2804
+ # SQUEEZE can compress a longer filled value until Hancom
2805
+ # renders adjacent glyphs on top of each other. New content
2806
+ # should wrap/reflow; untouched template cells keep their mode.
2807
+ sublist.set("lineWrap", "BREAK")
2799
2808
  if split_paragraphs:
2800
- self._set_split_paragraph_text(value)
2809
+ self._set_split_paragraph_text(sanitized_value)
2801
2810
  self.element.set("dirty", "1")
2802
2811
  self.table.mark_dirty()
2803
2812
  return
2804
2813
 
2805
2814
  text_element = self._ensure_text_element()
2806
- text_element.text = _sanitize_text(value)
2815
+ text_element.text = sanitized_value
2807
2816
  for node in self.element.findall(f".//{_HP}t"):
2808
2817
  if node is text_element:
2809
2818
  continue
@@ -182,6 +182,9 @@ def build_grid(table: bytes) -> tuple[dict[tuple[int, int], _Cell], GridReport]:
182
182
 
183
183
 
184
184
  _P_SPAN_RE = re.compile(rb"<(?:[A-Za-z_][\w.-]*:)?p\b.*?</(?:[A-Za-z_][\w.-]*:)?p>", re.DOTALL)
185
+ _SQUEEZE_WRAP_RE = re.compile(
186
+ rb'<(?:[A-Za-z_][\w.-]*:)?subList\b[^>]*?\blineWrap="(?P<value>SQUEEZE)"'
187
+ )
185
188
 
186
189
  def _first_paragraph_span(cell: bytes) -> tuple[int, int] | None:
187
190
  """Byte span of the cell's first ``<hp:p>...</hp:p>`` (its own subList's
@@ -196,6 +199,22 @@ def _all_paragraph_spans(cell: bytes) -> list[tuple[int, int]]:
196
199
  return [(m.start(), m.end()) for m in _P_SPAN_RE.finditer(masked)]
197
200
 
198
201
 
202
+ def _squeeze_wrap_edit(cell: bytes) -> tuple[int, int, bytes] | None:
203
+ """Return a minimal edit that makes a filled cell wrap instead of squeeze.
204
+
205
+ Hancom's ``lineWrap=SQUEEZE`` keeps long replacement text on the existing
206
+ line by compressing glyph advances. Template placeholders often fit, but
207
+ real filled values can become nearly unreadable even though their charPr
208
+ spacing is normal. Only the addressed cell's direct subList is considered;
209
+ nested tables remain untouched.
210
+ """
211
+
212
+ match = _SQUEEZE_WRAP_RE.search(_mask_nested_tables(cell))
213
+ if match is None:
214
+ return None
215
+ return match.start("value"), match.end("value"), b"BREAK"
216
+
217
+
199
218
  # --- font shrink-to-fit helpers (byte-preserving charPr materialisation) ------
200
219
 
201
220
  def _header_part_name(parts: Mapping[str, bytes]) -> str | None:
@@ -602,6 +621,17 @@ def fill_cells(
602
621
  continue
603
622
  if not cell_edits:
604
623
  continue
624
+ # A template's short placeholder may legitimately fit under
625
+ # lineWrap=SQUEEZE, while a real filled value is compressed until
626
+ # glyphs appear to overlap. Changed non-empty values must wrap and
627
+ # reflow; preserve SQUEEZE for no-op/clear operations.
628
+ if text.strip():
629
+ wrap_edit = _squeeze_wrap_edit(cell_bytes)
630
+ if wrap_edit is not None:
631
+ ws, we, replacement = wrap_edit
632
+ section_edits.append(
633
+ (ts + cell.start + ws, ts + cell.start + we, replacement)
634
+ )
605
635
  section_edits.extend(cell_edits)
606
636
  applied.append(CellApplied(section_path, ti, row, col, first_orig or "", text))
607
637
  if section_edits:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-hwpx
3
- Version: 2.24.0
3
+ Version: 2.24.1
4
4
  Summary: 한글 없이 HWPX 문서를 열고, 편집하고, 생성하고, 검증하는 Python 자동화 라이브러리
5
5
  Author: python-hwpx Maintainers
6
6
  License-Expression: Apache-2.0
@@ -20,7 +20,7 @@ Requires-Python: >=3.10
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
22
  License-File: NOTICE
23
- Requires-Dist: lxml<6,>=4.9
23
+ Requires-Dist: lxml<7,>=4.9
24
24
  Provides-Extra: visual
25
25
  Requires-Dist: pymupdf>=1.24; extra == "visual"
26
26
  Requires-Dist: pillow>=10.0; extra == "visual"
@@ -202,6 +202,15 @@ pip install -e ".[dev]"
202
202
  pytest
203
203
  ```
204
204
 
205
+ ## 감사의 말
206
+
207
+ 아래 공개 표준·프로젝트에 빚지고 있습니다.
208
+
209
+ - **[OWPML — 개방형 워드프로세서 마크업 언어 (KS X 6101)](https://www.kssn.net/search/stddetail.do?itemNo=K001010119985)** — HWPX가 기반하는 한국 산업 표준
210
+ - **[hancom-io/hwpx-owpml-model](https://github.com/hancom-io/hwpx-owpml-model)** — OWPML 요소 구조 참조 모델 · **[neolord0/hwpxlib](https://github.com/neolord0/hwpxlib)** — 오라클 샘플 코퍼스
211
+ - **[edwardkim/rhwp](https://github.com/edwardkim/rhwp)** — 멱등성·검증 게이트 설계 영감
212
+ - **범정부오피스** — 공무 문서 편집 워크플로 아이디어
213
+
205
214
  ## License
206
215
 
207
216
  Apache License 2.0. See LICENSE and NOTICE.
@@ -1,4 +1,4 @@
1
- lxml<6,>=4.9
1
+ lxml<7,>=4.9
2
2
 
3
3
  [dev]
4
4
  build>=1.0
@@ -405,6 +405,28 @@ def test_table_set_cell_text_removes_layout_cache() -> None:
405
405
  assert paragraph.find(f"{HP}linesegarray") is None
406
406
 
407
407
 
408
+ def test_table_set_cell_text_converts_squeeze_to_break() -> None:
409
+ section_element = ET.Element(f"{HS}sec")
410
+ section = HwpxOxmlSection("section0.xml", section_element)
411
+ manifest = ET.Element("manifest")
412
+ root = HwpxOxmlDocument(manifest, [section], [])
413
+ document = HwpxDocument(cast(HwpxPackage, object()), root)
414
+
415
+ table = document.add_table(1, 1, section=section)
416
+ cell = table.cell(0, 0)
417
+ sublist = cell.element.find(f"{HP}subList")
418
+ assert sublist is not None
419
+ sublist.set("lineWrap", "SQUEEZE")
420
+
421
+ table.set_cell_text(0, 0, "한 줄 폭을 넘는 신규 검토 의견 " * 8)
422
+
423
+ assert sublist.get("lineWrap") == "BREAK"
424
+
425
+ sublist.set("lineWrap", "SQUEEZE")
426
+ table.set_cell_text(0, 0, cell.text)
427
+ assert sublist.get("lineWrap") == "SQUEEZE"
428
+
429
+
408
430
  def test_save_removes_stale_layout_cache_after_low_level_text_edit() -> None:
409
431
  document = HwpxDocument.new()
410
432
  try:
@@ -107,6 +107,48 @@ def test_fill_changes_only_target_and_preserves_rest(simple):
107
107
  assert "CELL_FILLED_X" in sec2.decode("utf-8")
108
108
 
109
109
 
110
+ def test_fill_cell_converts_squeeze_to_break_only_in_touched_cell(merged):
111
+ _, sec = _section(merged)
112
+ targets = []
113
+ for ti, (start, end) in enumerate(_iter_table_spans(sec)):
114
+ table = sec[start:end]
115
+ for cell in _direct_cells(table):
116
+ cell_bytes = table[cell.start:cell.end]
117
+ if b'lineWrap="SQUEEZE"' in cell_bytes:
118
+ targets.append((ti, cell.row, cell.col))
119
+ assert len(targets) >= 2
120
+
121
+ ti, row, col = targets[0]
122
+ result = fill_cells(
123
+ merged,
124
+ [{"table_index": ti, "row": row, "col": col, "text": "긴 신규 검토 의견 " * 12}],
125
+ )
126
+ assert result.ok
127
+
128
+ _, changed_section = _section(result.data)
129
+ changed_spans = _iter_table_spans(changed_section)
130
+ changed_table = changed_section[changed_spans[ti][0]:changed_spans[ti][1]]
131
+ changed_cell = build_grid(changed_table)[0][(row, col)]
132
+ changed_cell_bytes = changed_table[changed_cell.start:changed_cell.end]
133
+ assert b'lineWrap="BREAK"' in changed_cell_bytes
134
+ assert b'lineWrap="SQUEEZE"' not in changed_cell_bytes
135
+
136
+ other_ti, other_row, other_col = targets[1]
137
+ other_table = changed_section[changed_spans[other_ti][0]:changed_spans[other_ti][1]]
138
+ other_cell = build_grid(other_table)[0][(other_row, other_col)]
139
+ assert b'lineWrap="SQUEEZE"' in other_table[other_cell.start:other_cell.end]
140
+
141
+ original_table = sec[_iter_table_spans(sec)[ti][0]:_iter_table_spans(sec)[ti][1]]
142
+ original_cell = build_grid(original_table)[0][(row, col)]
143
+ original_text = _cell_text(original_table, original_cell)
144
+ noop = fill_cells(
145
+ merged,
146
+ [{"table_index": ti, "row": row, "col": col, "text": original_text}],
147
+ )
148
+ assert noop.byte_identical is True
149
+ assert noop.data == merged
150
+
151
+
110
152
  def test_untouched_table_is_byte_identical(merged):
111
153
  _, sec = _section(merged)
112
154
  spans = _iter_table_spans(sec)
File without changes
File without changes
File without changes