python-hwpx 6.4.0__py3-none-any.whl → 6.5.0__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/equation/authoring.py +5 -0
- hwpx/equation/mathml.py +66 -0
- hwpx/equation/render.py +2 -2
- hwpx/equation/tokens.py +11 -0
- hwpx/oxml/_paragraph_text_edit.py +42 -0
- hwpx/oxml/paragraph.py +37 -0
- hwpx/oxml/table.py +24 -0
- {python_hwpx-6.4.0.dist-info → python_hwpx-6.5.0.dist-info}/METADATA +1 -1
- {python_hwpx-6.4.0.dist-info → python_hwpx-6.5.0.dist-info}/RECORD +14 -13
- {python_hwpx-6.4.0.dist-info → python_hwpx-6.5.0.dist-info}/WHEEL +0 -0
- {python_hwpx-6.4.0.dist-info → python_hwpx-6.5.0.dist-info}/entry_points.txt +0 -0
- {python_hwpx-6.4.0.dist-info → python_hwpx-6.5.0.dist-info}/licenses/LICENSE +0 -0
- {python_hwpx-6.4.0.dist-info → python_hwpx-6.5.0.dist-info}/licenses/NOTICE +0 -0
- {python_hwpx-6.4.0.dist-info → python_hwpx-6.5.0.dist-info}/top_level.txt +0 -0
hwpx/equation/authoring.py
CHANGED
|
@@ -78,6 +78,11 @@ _LATEX_TO_EQEDIT.update(
|
|
|
78
78
|
"\\forall": "FORALL",
|
|
79
79
|
"\\iint": "dint",
|
|
80
80
|
"\\iiint": "tint",
|
|
81
|
+
# ``triangle`` is accepted when reading (observed in real documents) but
|
|
82
|
+
# only the documented uppercase spelling is emitted when authoring: the
|
|
83
|
+
# lowercase form has not been render-verified, and lowercase ``forall``
|
|
84
|
+
# already turned out to render as literal text.
|
|
85
|
+
"\\triangle": "TRIANGLE",
|
|
81
86
|
# Common LaTeX aliases sharing a verified target.
|
|
82
87
|
"\\le": "leq",
|
|
83
88
|
"\\ge": "geq",
|
hwpx/equation/mathml.py
CHANGED
|
@@ -9,11 +9,16 @@ code block rather than dropping the equation.
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
import re
|
|
12
13
|
from typing import Callable
|
|
13
14
|
|
|
15
|
+
from .tokens import EQEDIT_MATHML_OPERATOR_COMMANDS
|
|
16
|
+
|
|
14
17
|
# ``False`` marks a resolved-but-unavailable converter; ``None`` means "not yet
|
|
15
18
|
# probed" so the import is attempted lazily on first use.
|
|
16
19
|
_converter: Callable[[str], str] | bool | None = None
|
|
20
|
+
_LATEX_WORD_COMMAND_RE = re.compile(r"\\[A-Za-z]+")
|
|
21
|
+
_TEXT_COMMAND = "\\text{"
|
|
17
22
|
|
|
18
23
|
|
|
19
24
|
class MathMLUnavailableError(RuntimeError):
|
|
@@ -62,8 +67,69 @@ def latex_to_mathml(latex: str) -> str:
|
|
|
62
67
|
raise ValueError(f"latex2mathml could not render fragment: {exc}") from exc
|
|
63
68
|
|
|
64
69
|
|
|
70
|
+
def eqedit_latex_to_mathml(latex: str) -> str:
|
|
71
|
+
"""Convert EqEdit-derived LaTeX while preserving known token roles.
|
|
72
|
+
|
|
73
|
+
``latex2mathml`` classifies plain ``\\triangle`` as an identifier. EqEdit's
|
|
74
|
+
token map identifies it as a mathematical symbol, so the MathML-only input
|
|
75
|
+
receives an operator wrapper before conversion. The returned/public LaTeX
|
|
76
|
+
is not rewritten, and serialized MathML is never patched afterward.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def annotate_role(match: re.Match[str]) -> str:
|
|
80
|
+
command = match.group(0)
|
|
81
|
+
if command in EQEDIT_MATHML_OPERATOR_COMMANDS:
|
|
82
|
+
return rf"\mathop{{{command}}}"
|
|
83
|
+
return command
|
|
84
|
+
|
|
85
|
+
return latex_to_mathml(
|
|
86
|
+
"".join(
|
|
87
|
+
segment if literal else _LATEX_WORD_COMMAND_RE.sub(annotate_role, segment)
|
|
88
|
+
for segment, literal in _split_text_literals(latex)
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _split_text_literals(latex: str) -> list[tuple[str, bool]]:
|
|
94
|
+
"""Split ``latex`` into ``(segment, is_text_literal)`` pieces.
|
|
95
|
+
|
|
96
|
+
Quoted EqEdit literals become ``\\text{...}``; their content is prose, so
|
|
97
|
+
the role annotation must not rewrite a ``\\triangle`` typed inside quotes.
|
|
98
|
+
Braces inside the literal are balanced; an unterminated group is passed
|
|
99
|
+
through untouched so ``latex2mathml`` reports it instead of this splitter.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
pieces: list[tuple[str, bool]] = []
|
|
103
|
+
cursor = 0
|
|
104
|
+
while True:
|
|
105
|
+
start = latex.find(_TEXT_COMMAND, cursor)
|
|
106
|
+
if start < 0:
|
|
107
|
+
break
|
|
108
|
+
depth = 0
|
|
109
|
+
end = -1
|
|
110
|
+
for index in range(start + len(_TEXT_COMMAND) - 1, len(latex)):
|
|
111
|
+
char = latex[index]
|
|
112
|
+
if char == "{":
|
|
113
|
+
depth += 1
|
|
114
|
+
elif char == "}":
|
|
115
|
+
depth -= 1
|
|
116
|
+
if depth == 0:
|
|
117
|
+
end = index + 1
|
|
118
|
+
break
|
|
119
|
+
if end < 0:
|
|
120
|
+
break
|
|
121
|
+
if start > cursor:
|
|
122
|
+
pieces.append((latex[cursor:start], False))
|
|
123
|
+
pieces.append((latex[start:end], True))
|
|
124
|
+
cursor = end
|
|
125
|
+
if cursor < len(latex):
|
|
126
|
+
pieces.append((latex[cursor:], False))
|
|
127
|
+
return pieces
|
|
128
|
+
|
|
129
|
+
|
|
65
130
|
__all__ = [
|
|
66
131
|
"MathMLUnavailableError",
|
|
132
|
+
"eqedit_latex_to_mathml",
|
|
67
133
|
"latex2mathml_available",
|
|
68
134
|
"latex_to_mathml",
|
|
69
135
|
]
|
hwpx/equation/render.py
CHANGED
|
@@ -18,7 +18,7 @@ from dataclasses import dataclass
|
|
|
18
18
|
import html
|
|
19
19
|
|
|
20
20
|
from .eqedit import EquationConversionError, eqedit_to_latex
|
|
21
|
-
from .mathml import MathMLUnavailableError,
|
|
21
|
+
from .mathml import MathMLUnavailableError, eqedit_latex_to_mathml
|
|
22
22
|
|
|
23
23
|
# Fidelity labels surfaced in the preview (Constitution IX, honest reporting).
|
|
24
24
|
LABEL_MATHML = "수식 MathML 렌더"
|
|
@@ -63,7 +63,7 @@ def render_equation(script: str) -> EquationRender:
|
|
|
63
63
|
return _fallback_block("script", LABEL_SCRIPT, script, latex=None)
|
|
64
64
|
|
|
65
65
|
try:
|
|
66
|
-
mathml =
|
|
66
|
+
mathml = eqedit_latex_to_mathml(latex)
|
|
67
67
|
except MathMLUnavailableError:
|
|
68
68
|
return _fallback_block("latex", LABEL_LATEX_NO_LIB, latex, latex=latex)
|
|
69
69
|
except ValueError:
|
hwpx/equation/tokens.py
CHANGED
|
@@ -116,6 +116,11 @@ OPERATORS: dict[str, str] = {
|
|
|
116
116
|
"partial": r"\partial",
|
|
117
117
|
"nabla": r"\nabla",
|
|
118
118
|
"angle": r"\angle",
|
|
119
|
+
# Hancom's symbol guide spells this token in uppercase, while legacy
|
|
120
|
+
# documents also contain the exact lowercase form. Mixed-case variants are
|
|
121
|
+
# intentionally not accepted because the reader uses exact token lookup.
|
|
122
|
+
"triangle": r"\triangle",
|
|
123
|
+
"TRIANGLE": r"\triangle",
|
|
119
124
|
"cdots": r"\cdots",
|
|
120
125
|
"ldots": r"\ldots",
|
|
121
126
|
"vdots": r"\vdots",
|
|
@@ -254,11 +259,17 @@ DELIMITERS: dict[str, str] = {
|
|
|
254
259
|
# Structural keywords handled directly by the parser (not simple substitution).
|
|
255
260
|
STRUCTURAL = frozenset({"over", "atop", "sqrt", "root", "of", "LEFT", "RIGHT", "left", "right"})
|
|
256
261
|
|
|
262
|
+
# LaTeX commands emitted from EqEdit operator tokens that latex2mathml otherwise
|
|
263
|
+
# classifies as identifiers. The render boundary uses this metadata only while
|
|
264
|
+
# producing MathML; the public LaTeX remains the canonical command above.
|
|
265
|
+
EQEDIT_MATHML_OPERATOR_COMMANDS = frozenset({OPERATORS["triangle"]})
|
|
266
|
+
|
|
257
267
|
|
|
258
268
|
__all__ = [
|
|
259
269
|
"ACCENTS",
|
|
260
270
|
"BIG_OPERATORS",
|
|
261
271
|
"DELIMITERS",
|
|
272
|
+
"EQEDIT_MATHML_OPERATOR_COMMANDS",
|
|
262
273
|
"FUNCTIONS",
|
|
263
274
|
"GREEK",
|
|
264
275
|
"MATRIX_ENVIRONMENTS",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Small helpers for a style-preserving paragraph text edit."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import xml.etree.ElementTree as ET
|
|
7
|
+
|
|
8
|
+
from ..errors import HwpxValueError
|
|
9
|
+
from ._document_primitives import _is_tab_control_element
|
|
10
|
+
from .namespaces import tag_local_name
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def plain_text_nodes_for_edit(runs: list[ET.Element]) -> list[ET.Element]:
|
|
14
|
+
nodes: list[ET.Element] = []
|
|
15
|
+
for run in runs:
|
|
16
|
+
for child in run:
|
|
17
|
+
if tag_local_name(child.tag) == "t":
|
|
18
|
+
if len(child):
|
|
19
|
+
raise HwpxValueError(
|
|
20
|
+
"mixed text markup cannot be edited safely",
|
|
21
|
+
code="paragraph-mixed-text-unsupported",
|
|
22
|
+
)
|
|
23
|
+
nodes.append(child)
|
|
24
|
+
elif tag_local_name(child.tag) == "tab" or _is_tab_control_element(child):
|
|
25
|
+
raise HwpxValueError(
|
|
26
|
+
"tab controls require an explicit run target",
|
|
27
|
+
code="paragraph-tab-target-required",
|
|
28
|
+
)
|
|
29
|
+
return nodes
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def edit_node_candidates(
|
|
33
|
+
nodes: list[ET.Element], prefix: int, end: int
|
|
34
|
+
) -> list[tuple[ET.Element, int]]:
|
|
35
|
+
offset = 0
|
|
36
|
+
candidates: list[tuple[ET.Element, int]] = []
|
|
37
|
+
for node in nodes:
|
|
38
|
+
length = len(node.text or "")
|
|
39
|
+
if offset <= prefix and end <= offset + length:
|
|
40
|
+
candidates.append((node, offset))
|
|
41
|
+
offset += length
|
|
42
|
+
return candidates
|
hwpx/oxml/paragraph.py
CHANGED
|
@@ -40,6 +40,7 @@ from .note_authoring import (
|
|
|
40
40
|
_paragraph_endnotes,
|
|
41
41
|
_paragraph_footnotes,
|
|
42
42
|
)
|
|
43
|
+
from ._paragraph_text_edit import edit_node_candidates, plain_text_nodes_for_edit
|
|
43
44
|
from .objects import (
|
|
44
45
|
HwpxOxmlInlineObject,
|
|
45
46
|
_create_picture_element,
|
|
@@ -336,6 +337,42 @@ class HwpxOxmlParagraph:
|
|
|
336
337
|
_clear_paragraph_layout_cache(self.element)
|
|
337
338
|
self.section.mark_dirty()
|
|
338
339
|
|
|
340
|
+
def set_text_preserving_runs(self, value: str) -> None:
|
|
341
|
+
"""Replace one unambiguous text span without changing run boundaries.
|
|
342
|
+
|
|
343
|
+
The edit must fit inside one plain ``hp:t`` node. This covers a
|
|
344
|
+
correction within a styled run while retaining every other run and
|
|
345
|
+
control; cross-style replacements require an explicit run target.
|
|
346
|
+
"""
|
|
347
|
+
from ..errors import HwpxValueError
|
|
348
|
+
|
|
349
|
+
nodes = plain_text_nodes_for_edit(self._run_elements())
|
|
350
|
+
old = "".join(node.text or "" for node in nodes)
|
|
351
|
+
if old == value:
|
|
352
|
+
return
|
|
353
|
+
if not nodes:
|
|
354
|
+
raise HwpxValueError("paragraph has no plain text node", code="paragraph-text-missing")
|
|
355
|
+
prefix = 0
|
|
356
|
+
while prefix < min(len(old), len(value)) and old[prefix] == value[prefix]:
|
|
357
|
+
prefix += 1
|
|
358
|
+
suffix = 0
|
|
359
|
+
while (suffix < len(old) - prefix and suffix < len(value) - prefix
|
|
360
|
+
and old[len(old) - suffix - 1] == value[len(value) - suffix - 1]):
|
|
361
|
+
suffix += 1
|
|
362
|
+
end = len(old) - suffix
|
|
363
|
+
replacement = value[prefix:len(value) - suffix if suffix else len(value)]
|
|
364
|
+
candidates = edit_node_candidates(nodes, prefix, end)
|
|
365
|
+
if len(candidates) != 1:
|
|
366
|
+
raise HwpxValueError(
|
|
367
|
+
"text edit crosses run boundaries or has ambiguous insertion style",
|
|
368
|
+
code="paragraph-text-style-ambiguous",
|
|
369
|
+
)
|
|
370
|
+
node, offset = candidates[0]
|
|
371
|
+
current = node.text or ""
|
|
372
|
+
node.text = _sanitize_text(current[:prefix - offset] + replacement + current[end - offset:])
|
|
373
|
+
_clear_paragraph_layout_cache(self.element)
|
|
374
|
+
self.section.mark_dirty()
|
|
375
|
+
|
|
339
376
|
def clear_text(self) -> None:
|
|
340
377
|
"""Remove all text content while preserving styles and non-text elements.
|
|
341
378
|
|
hwpx/oxml/table.py
CHANGED
|
@@ -464,6 +464,30 @@ class HwpxOxmlTable:
|
|
|
464
464
|
")"
|
|
465
465
|
)
|
|
466
466
|
|
|
467
|
+
@property
|
|
468
|
+
def height(self) -> int:
|
|
469
|
+
"""Declared table height in HWP units."""
|
|
470
|
+
size = self.element.find(f"{_HP}sz")
|
|
471
|
+
return int(size.get("height", "0")) if size is not None else 0
|
|
472
|
+
|
|
473
|
+
@property
|
|
474
|
+
def treat_as_char(self) -> bool:
|
|
475
|
+
"""Whether Hancom lays out this table as one inline character."""
|
|
476
|
+
position = self.element.find(f"{_HP}pos")
|
|
477
|
+
return position is not None and position.get("treatAsChar", "1") == "1"
|
|
478
|
+
|
|
479
|
+
def set_treat_as_char(self, value: bool) -> None:
|
|
480
|
+
"""Choose inline layout or flowing table layout across pages."""
|
|
481
|
+
position = self.element.find(f"{_HP}pos")
|
|
482
|
+
if position is None:
|
|
483
|
+
from ..errors import HwpxValueError
|
|
484
|
+
|
|
485
|
+
raise HwpxValueError("table has no hp:pos", code="table-position-missing")
|
|
486
|
+
desired = "1" if value else "0"
|
|
487
|
+
if position.get("treatAsChar") != desired:
|
|
488
|
+
position.set("treatAsChar", desired)
|
|
489
|
+
self.mark_dirty()
|
|
490
|
+
|
|
467
491
|
# --- caption (hp:caption) -----------------------------------------
|
|
468
492
|
|
|
469
493
|
@property
|
|
@@ -43,11 +43,11 @@ hwpx/data/contract_docs/mutation-semantics.md,sha256=3GjuRgPd7W58y9N1aj7xK10U4DZ
|
|
|
43
43
|
hwpx/data/contract_docs/recipes-traversal.md,sha256=tj9CsabtI4EmiFmUdNz4MwBQm4apS12s6uZ5v9vek0M,4419
|
|
44
44
|
hwpx/data/contract_docs/support-matrix.md,sha256=vODB2JsgEGFRFHkeEQovwy6McxBSEimjlkhIG4N-93Y,65733
|
|
45
45
|
hwpx/equation/__init__.py,sha256=0wks0_pS_tBokCVMeWUJGE6tbW35Ptc0I5Z_36FY-Jo,1328
|
|
46
|
-
hwpx/equation/authoring.py,sha256=
|
|
46
|
+
hwpx/equation/authoring.py,sha256=xuLRxkIPPJmiDfSVX-ngcQYYKZRqSuHV1PBVvBvo6vY,17117
|
|
47
47
|
hwpx/equation/eqedit.py,sha256=FjRNwc_JVC01yprqLFk5N6Nm5qCow2K2x-u3Dw7Wmio,11314
|
|
48
|
-
hwpx/equation/mathml.py,sha256=
|
|
49
|
-
hwpx/equation/render.py,sha256=
|
|
50
|
-
hwpx/equation/tokens.py,sha256=
|
|
48
|
+
hwpx/equation/mathml.py,sha256=Wbuw9hikBJoxzUdKjMDasvBe8suGGjNUXBTeNrp-GSM,4424
|
|
49
|
+
hwpx/equation/render.py,sha256=P475CF6xhEYveDgw2aiEHhg9TW-3ZTs3MlpyzU5PPvY,2888
|
|
50
|
+
hwpx/equation/tokens.py,sha256=76T57UgeE-08NVPHjN0FD3wvxvIdPksbxgjegvUgf5w,7729
|
|
51
51
|
hwpx/form_fit/__init__.py,sha256=l1HcFge4u_wL2vogB-VxSMrb-8h7zUT_IgTWMtnH9CM,1779
|
|
52
52
|
hwpx/form_fit/apply.py,sha256=X2q7K-mLku4AXxm4-xP80QGzhBlpzpqA_Ade8aPXzNY,3450
|
|
53
53
|
hwpx/form_fit/engine.py,sha256=2W5ePGnpaLDoVPH8RxKdRfVx3r3usy26RBWj0jU1fpE,21553
|
|
@@ -74,6 +74,7 @@ hwpx/opc/xml_utils.py,sha256=r4wc0irlf4tOXlOAwXoqReJOY3-EIqd7Uan56XR6dBs,4474
|
|
|
74
74
|
hwpx/oxml/__init__.py,sha256=Ogl__NFyPORPxboCHqrsn2IrRdcjaQBzmnYm4pPWXpA,6731
|
|
75
75
|
hwpx/oxml/_document_impl.py,sha256=41cxktJqXHER37fjA5HIFR8kw7dHMoISTxEv53PRBYo,5367
|
|
76
76
|
hwpx/oxml/_document_primitives.py,sha256=IcGRT7B4gblNgJ5XDivV_DME-5cU5p88hRSAM1L8_Hk,56887
|
|
77
|
+
hwpx/oxml/_paragraph_text_edit.py,sha256=8IHjDPRh1yXtCYSbL0LER9Z4_wVnXybpCh3qQ8jwmPo,1453
|
|
77
78
|
hwpx/oxml/body.py,sha256=RRopsZ7rvHDMIYNoEwHPty7DXyaZaFRDqJQSI6gVIls,52196
|
|
78
79
|
hwpx/oxml/canonical_defaults.py,sha256=WHAK7u_W-PDv3P3N1-1-aWAoiUgBh4x-UybFL4NqW-w,3791
|
|
79
80
|
hwpx/oxml/color.py,sha256=K2lbU_JdqRxFkQelGD6BbBkH1IspJSQyGlKHNz1Nmf4,2393
|
|
@@ -96,7 +97,7 @@ hwpx/oxml/note_authoring.py,sha256=xOoYeX640XkwdftUQeHsdojGHHbiLbobZPi3aahh5ek,7
|
|
|
96
97
|
hwpx/oxml/numbering.py,sha256=9a0ARGW1DkKsTF7mEEXM4FA5loQmzIBuqE4APA8UFIQ,669
|
|
97
98
|
hwpx/oxml/numbering_kinds.py,sha256=dikaExXr8GZ0gNL4KM5xxvGQOZDCkCdcA5qKDLsstsg,4034
|
|
98
99
|
hwpx/oxml/objects.py,sha256=kL4xy0tBmq8E598sJ67bY2xk5Zwg09apelPqQGnD44w,55570
|
|
99
|
-
hwpx/oxml/paragraph.py,sha256=
|
|
100
|
+
hwpx/oxml/paragraph.py,sha256=2TN9XDwBUNA4qFBh7yTPM9M43zpnA-x_grsevh_B7fE,62747
|
|
100
101
|
hwpx/oxml/parser.py,sha256=pIfyNdW3WdFkCcE8JFY7hn1fobRbMngzfhVZICvWeVs,2937
|
|
101
102
|
hwpx/oxml/run.py,sha256=khz9hf2_YpQjYSNR5Qq8XKJ4EmGfiJu9LtfCfLgblnU,16375
|
|
102
103
|
hwpx/oxml/schema.py,sha256=ElR3_IIhhPPZEqJtNKMNCHA-VFVLdhL454W_4spuvlc,1284
|
|
@@ -106,7 +107,7 @@ hwpx/oxml/section_layout.py,sha256=TyzddL31pdKSFWYfxVKdIjs3vo8UiG0lERa5-X6bKHI,5
|
|
|
106
107
|
hwpx/oxml/section_story.py,sha256=OqCXk78gPL0ILQJqDBnhmjtq_tUru0j23IeXXpoWApA,25896
|
|
107
108
|
hwpx/oxml/settings.py,sha256=0cI0zODpxwUgcleVR0J6I4nGT3FGSW8CI0qxwZHXaAk,5523
|
|
108
109
|
hwpx/oxml/simple_parts.py,sha256=XpeVmBWOjv1UVN6sGbskYqwyCIDsNSgzsnnG4QG80Us,3810
|
|
109
|
-
hwpx/oxml/table.py,sha256=
|
|
110
|
+
hwpx/oxml/table.py,sha256=Pgy3vW2sS2SqLEcnrQVaV8uHmmWivE5C86yX-fNrSlA,57561
|
|
110
111
|
hwpx/oxml/utils.py,sha256=2L9au3SD_MFkFt2DXx3udXBT5caYuYO623lhGhgldVo,2972
|
|
111
112
|
hwpx/oxml/version_part.py,sha256=kFXKQUKgClrM-LuVvBEaSD4RePV1kk1Kt8ltgttefS8,2627
|
|
112
113
|
hwpx/plan/__init__.py,sha256=WvlBce8ic63hf8MsA6x-K_1BVrkNu6gaxKVIM7Axxks,1471
|
|
@@ -153,10 +154,10 @@ hwpx/tools/toc_fidelity.py,sha256=rvoKH8QJ65WNVrxS0d-i2AtODvBy-4O8NRudfQ244v4,19
|
|
|
153
154
|
hwpx/tools/validator.py,sha256=U856izL9NcJZOiKDYoCpwOSaFNQ2Un8Jn4pzL20A96Q,7100
|
|
154
155
|
hwpx/tools/_schemas/header.xsd,sha256=mJXuFMuHGT1JnFFaluUpYUglwjMCNlfbFCRVM26eHXE,664
|
|
155
156
|
hwpx/tools/_schemas/section.xsd,sha256=MgvavVHG05RDfUnVPxVU10H4FQOja5ON04_m9Uk_m7E,522
|
|
156
|
-
python_hwpx-6.
|
|
157
|
-
python_hwpx-6.
|
|
158
|
-
python_hwpx-6.
|
|
159
|
-
python_hwpx-6.
|
|
160
|
-
python_hwpx-6.
|
|
161
|
-
python_hwpx-6.
|
|
162
|
-
python_hwpx-6.
|
|
157
|
+
python_hwpx-6.5.0.dist-info/licenses/LICENSE,sha256=_ubz4wv-BkkT3l3gu-QuH7JGeVjuRYGZoZK95eNsCHU,9688
|
|
158
|
+
python_hwpx-6.5.0.dist-info/licenses/NOTICE,sha256=he3PBLXnIZK0sNsozc-SAQ2jvWjV61goylWUZ8HPi3s,3837
|
|
159
|
+
python_hwpx-6.5.0.dist-info/METADATA,sha256=MLawxpU4hei8fmJR8XZXiU2Mc-RBjnI3dHxuywHr7tE,14995
|
|
160
|
+
python_hwpx-6.5.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
161
|
+
python_hwpx-6.5.0.dist-info/entry_points.txt,sha256=JUKRxbly9UaeHV7YzOea23y8IiqSTcrhUlooP3fS_Zc,405
|
|
162
|
+
python_hwpx-6.5.0.dist-info/top_level.txt,sha256=R1iToqDh80Nf2oQhRjTN0rbN2X6kyDUizIocZjkhuxc,5
|
|
163
|
+
python_hwpx-6.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|