Skip to content

airmang/python-hwpx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

86 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

python-hwpx

HWPX ๋ฌธ์„œ๋ฅผ Python์œผ๋กœ ์ฝ๊ณ , ํŽธ์ง‘ํ•˜๊ณ , ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

PyPI Python License: Custom Non-Commercial Docs


python-hwpx๋Š” ํ•œ์ปด์˜คํ”ผ์Šค์˜ HWPX ํฌ๋งท์„ ์ˆœ์ˆ˜ Python์œผ๋กœ ๋‹ค๋ฃจ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด์ž CLI ๋„๊ตฌ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค. ํ•œ/๊ธ€ ์„ค์น˜ ์—†์ด, OS์— ๊ด€๊ณ„์—†์ด HWPX ๋ฌธ์„œ์˜ ๊ตฌ์กฐ๋ฅผ ํŒŒ์‹ฑํ•˜๊ณ  ์ฝ˜ํ…์ธ ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ ํŽธ์ง‘ API๋ฟ ์•„๋‹ˆ๋ผ ์Šคํ‚ค๋งˆ/ํŒจํ‚ค์ง€ ๊ฒ€์ฆ, unpack/pack, ํ…œํ”Œ๋ฆฟ ๋ถ„์„ ๊ฐ™์€ XML-first ์›Œํฌํ”Œ๋กœ๋„ ํ•จ๊ป˜ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

pyhwpx / pyhwp์™€ ๋‹ค๋ฅธ ์ ?

python-hwpx pyhwpx pyhwp
๋Œ€์ƒ ํฌ๋งท .hwpx (OWPML/OPC) .hwpx .hwp (v5 ๋ฐ”์ด๋„ˆ๋ฆฌ)
ํ•œ/๊ธ€ ์„ค์น˜ ๋ถˆํ•„์š” ํ•„์š” (Windows COM) ๋ถˆํ•„์š”
ํฌ๋กœ์Šค ํ”Œ๋žซํผ โœ… Linux / macOS / Windows / CI โŒ Windows ์ „์šฉ โœ…
๋ฐฉ์‹ ์ง์ ‘ XML ํŒŒ์‹ฑ COM ์ž๋™ํ™” OLE ํŒŒ์‹ฑ

๐ŸŒ ํฌ๋กœ์Šค ํ”Œ๋žซํผ ์ง€์›

HWPX ํŒŒ์ผ์€ ZIP + XML ๊ตฌ์กฐ์ด๋ฏ€๋กœ, ํ•œ/๊ธ€ ํ”„๋กœ๊ทธ๋žจ ์—†์ด Python๋งŒ์œผ๋กœ ์ฝ๊ณ  ํŽธ์ง‘ํ•˜๋Š” ์›Œํฌํ”Œ๋กœ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”Œ๋žซํผ ์ฝ๊ธฐ ์“ฐ๊ธฐ ๋น„๊ณ 
โœ… Windows โœ… โœ… ํ•œ์ปด์˜คํ”ผ์Šค
โœ… macOS โœ… โœ… ํ•œ์ปด์˜คํ”ผ์Šค Mac
โœ… Linux โœ… โœ… ํ•œ์ปด์˜คํ”ผ์Šค Linux
โœ… CI/CD โœ… โœ… Docker, GitHub Actions ๋“ฑ

์„ค์น˜

pip install python-hwpx

์œ ์ผํ•œ ์˜์กด์„ฑ์€ lxml์ž…๋‹ˆ๋‹ค.

Quick Start

from hwpx import HwpxDocument

# ๋นˆ ๋ฌธ์„œ ์ƒˆ๋กœ ๋งŒ๋“ค๊ธฐ
doc = HwpxDocument.new()

# ๊ธฐ์กด ๋ฌธ์„œ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๋ฉด:
# doc = HwpxDocument.open("๋ณด๊ณ ์„œ.hwpx")

# ๋ฌธ๋‹จ ์ถ”๊ฐ€
paragraph = doc.add_paragraph("python-hwpx๋กœ ์ƒ์„ฑํ•œ ๋ฌธ๋‹จ์ž…๋‹ˆ๋‹ค.")

# ํ‘œ ์ถ”๊ฐ€ (2ร—3)
table = doc.add_table(rows=2, cols=3)
table.set_cell_text(0, 0, "์ด๋ฆ„")
table.set_cell_text(0, 1, "๋ถ€์„œ")
table.set_cell_text(0, 2, "์—ฐ๋ฝ์ฒ˜")

# ๋ฉ”๋ชจ ์ถ”๊ฐ€ (๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ์˜ memo shape ์‚ฌ์šฉ)
doc.add_memo_with_anchor("๊ฒ€ํ†  ํ•„์š”", paragraph=paragraph, memo_shape_id_ref="0")

# ์ €์žฅ
doc.save_to_path("๊ฒฐ๊ณผ๋ฌผ.hwpx")

๐Ÿ’ก ์ปจํ…์ŠคํŠธ ๋งค๋‹ˆ์ €๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค:

with HwpxDocument.open("๋ณด๊ณ ์„œ.hwpx") as doc:
    doc.add_paragraph("์ž๋™์œผ๋กœ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.")
    doc.save_to_path("๊ฒฐ๊ณผ๋ฌผ.hwpx")

์ฃผ์š” ๊ธฐ๋Šฅ ํ•œ๋ˆˆ์— ๋ณด๊ธฐ

์นดํ…Œ๊ณ ๋ฆฌ ๊ธฐ๋Šฅ ์„ค๋ช…
๐Ÿ“„ ๋ฌธ์„œ I/O ์—ด๊ธฐ/์ €์žฅ/์ƒ์„ฑ ํŒŒ์ผ, ๋ฐ”์ดํŠธ, ์ŠคํŠธ๋ฆผ ์ž…์ถœ๋ ฅ ยท ์›์ž์  ์ €์žฅ ยท ZIP ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ
๐Ÿ“ ๋‹จ๋ฝ ์ถ”๊ฐ€/์‚ญ์ œ/ํŽธ์ง‘/์„œ์‹ ํ…์ŠคํŠธ ์„ค์ •, ๋‹จ๋ฝ ์‚ญ์ œ(remove_paragraph), ์Šคํƒ€์ผ ์ฐธ์กฐ
โœ๏ธ Run ํ…์ŠคํŠธ ์กฐ๊ฐ ์ถ”๊ฐ€, ๊ต์ฒด, ๋ณผ๋“œ/์ดํƒค๋ฆญ/๋ฐ‘์ค„/์ƒ‰์ƒ ์„œ์‹
๐Ÿ“Š ํ‘œ(Table) ์ƒ์„ฑ/ํŽธ์ง‘/๋ณ‘ํ•ฉ Nร—M ํ‘œ ์ƒ์„ฑ, ์…€ ํ…์ŠคํŠธ, ์…€ ๋ณ‘ํ•ฉ/๋ถ„ํ• , ์ค‘์ฒฉ ํ…Œ์ด๋ธ”
๐Ÿงญ ํ‘œ ์ž๋™ํ™” ํƒ์ƒ‰/์ฑ„์šฐ๊ธฐ ํ…Œ์ด๋ธ” ๋งต, ๋ผ๋ฒจ ๊ธฐ๋ฐ˜ ์…€ ํƒ์ƒ‰, ๊ฒฝ๋กœ ๊ธฐ๋ฐ˜ ๋ฐฐ์น˜ ์ฑ„์šฐ๊ธฐ
๐Ÿ“‘ ์„น์…˜ ์ถ”๊ฐ€/์‚ญ์ œ add_section(after=), remove_section(), manifest ์ž๋™ ๊ด€๋ฆฌ
๐Ÿ–ผ๏ธ ์ด๋ฏธ์ง€ ์ž„๋ฒ ๋“œ/์‚ญ์ œ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ, manifest ์ž๋™ ๋“ฑ๋ก
โœ๏ธ ๋„ํ˜• ์„ /์‚ฌ๊ฐํ˜•/ํƒ€์› OWPML ๋ช…์„ธ ์ค€์ˆ˜ ๋„ํ˜• ์‚ฝ์ž…
๐Ÿ“‘ ๋จธ๋ฆฌ๊ธ€/๋ฐ”๋‹ฅ๊ธ€ ์„ค์ •/์ œ๊ฑฐ ํ™€์ˆ˜/์ง์ˆ˜/์–‘์ชฝ ํŽ˜์ด์ง€ ๊ตฌ๋ถ„
๐Ÿ’ฌ ๋ฉ”๋ชจ ์ถ”๊ฐ€/์‚ญ์ œ ์•ต์ปค ๊ธฐ๋ฐ˜ ๋ฉ”๋ชจ, ๋ฉ”๋ชจ ์…ฐ์ดํ”„ ์ฐธ์กฐ
๐Ÿ“Œ ๊ฐ์ฃผ/๋ฏธ์ฃผ ์ถ”๊ฐ€ ํ…์ŠคํŠธ ์ ‘๊ทผ
๐Ÿ”— ๋ถ๋งˆํฌ/ํ•˜์ดํผ๋งํฌ ์‚ฝ์ž…/์กฐํšŒ URL ๋งํฌ, ๋‚ด๋ถ€ ๋ถ๋งˆํฌ
๐Ÿ“ฐ ๋‹ค๋‹จ ํŽธ์ง‘ ์ปฌ๋Ÿผ ์ •์˜ ๋‹ค๋‹จ ๋ ˆ์ด์•„์›ƒ ์ œ์–ด
๐Ÿ” ํ…์ŠคํŠธ ์ถ”์ถœ ํŒŒ์ดํ”„๋ผ์ธ ์„น์…˜/๋‹จ๋ฝ ์ˆœํšŒ, ์ฃผ์„ ๋ Œ๋”๋ง, ์ค‘์ฒฉ ๊ฐ์ฒด ์ œ์–ด
๐Ÿ”Ž ๊ฐ์ฒด ๊ฒ€์ƒ‰ ํƒœ๊ทธ/์†์„ฑ/XPath ํŠน์ • ์š”์†Œ ํƒ์ƒ‰, ์ฃผ์„ ์ดํ„ฐ๋ ˆ์ดํ„ฐ
๐ŸŽจ ์Šคํƒ€์ผ ์น˜ํ™˜ ์„œ์‹ ๊ธฐ๋ฐ˜ ํ•„ํ„ฐ ์ƒ‰์ƒ/๋ฐ‘์ค„/charPrIDRef ๊ธฐ๋ฐ˜ Run ๊ฒ€์ƒ‰ ๋ฐ ๊ต์ฒด
๐Ÿ“ค ๋‚ด๋ณด๋‚ด๊ธฐ ํ…์ŠคํŠธ/HTML/Markdown ๋ฌธ์„œ ๋ณ€ํ™˜ ์ถœ๋ ฅ
โœ… ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ XSD + ํŒจํ‚ค์ง€ ๊ตฌ์กฐ CLI(hwpx-validate, hwpx-validate-package) ๋ฐ API
๐Ÿงฐ ์ž‘์—… ๋„๊ตฌ unpack/pack/๋ถ„์„/๋น„๊ต pack-ready ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ ์ถ”์ถœ๊ณผ ์žฌ๊ตฌ์„ฑ ์ ๊ฒ€
๐Ÿ—๏ธ ์ €์ˆ˜์ค€ XML ๋ฐ์ดํ„ฐํด๋ž˜์Šค ๋งคํ•‘ OWPML ์Šคํ‚ค๋งˆ โ†” Python ๊ฐ์ฒด ์ง์ ‘ ์กฐ์ž‘
๐Ÿ”„ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ํ˜ธํ™˜ ์ž๋™ ์ •๊ทœํ™” HWPML 2016 โ†’ 2011 ์ž๋™ ๋ณ€ํ™˜

๊ธฐ๋Šฅ ์ƒ์„ธ

๐Ÿ“„ ๋ฌธ์„œ ํŽธ์ง‘

๋ฌธ๋‹จ, ํ‘œ, ๋ฉ”๋ชจ, ๋จธ๋ฆฌ๊ธ€/๋ฐ”๋‹ฅ๊ธ€์„ Python ๊ฐ์ฒด๋กœ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

# ๋‹จ๋ฝ ์ถ”๊ฐ€ยท์‚ญ์ œ
doc.add_paragraph("์ƒˆ ๋ฌธ๋‹จ")
doc.remove_paragraph(doc.paragraphs[-1])   # ๋งˆ์ง€๋ง‰ ๋‹จ๋ฝ ์‚ญ์ œ

# ์„น์…˜ ์ถ”๊ฐ€ยท์‚ญ์ œ
new_sec = doc.add_section()          # ๋ฌธ์„œ ๋์— ์„น์…˜ ์ถ”๊ฐ€
new_sec.add_paragraph("๋‘ ๋ฒˆ์งธ ์„น์…˜ ๋‚ด์šฉ")
doc.remove_section(1)                # ์ธ๋ฑ์Šค๋กœ ์„น์…˜ ์‚ญ์ œ

# ๋จธ๋ฆฌ๊ธ€ยท๋ฐ”๋‹ฅ๊ธ€
doc.set_header_text("๊ธฐ๋ฐ€ ๋ฌธ์„œ", page_type="BOTH")
doc.set_footer_text("1 / 10", page_type="BOTH")

# ํ‘œ ์…€ ๋ณ‘ํ•ฉยท๋ถ„ํ• 
table.merge_cells(0, 0, 1, 1)   # (0,0)~(1,1) ๋ณ‘ํ•ฉ
table.set_cell_text(0, 0, "๋ณ‘ํ•ฉ๋œ ์…€", logical=True, split_merged=True)

# ์–‘์‹ํ˜• ํ‘œ ์ž๋™ ์ฑ„์šฐ๊ธฐ
form = doc.add_table(2, 2)
form.cell(0, 0).text = "์„ฑ๋ช…:"
form.cell(1, 0).text = "์†Œ์†"

doc.find_cell_by_label("์„ฑ๋ช…")    # {"matches": [...], "count": 1}
doc.fill_by_path({
    "์„ฑ๋ช… > right": "ํ™๊ธธ๋™",
    "์†Œ์† > right": "ํ”Œ๋žซํผํŒ€",
})

๐Ÿ” ํ…์ŠคํŠธ ์ถ”์ถœ & ๊ฒ€์ƒ‰

from hwpx import TextExtractor, ObjectFinder

# ํ…์ŠคํŠธ ์ถ”์ถœ
with TextExtractor("๋ฌธ์„œ.hwpx") as extractor:
    for section in extractor.iter_sections():
        for para in extractor.iter_paragraphs(section):
            print(para.text())

# ํŠน์ • ๊ฐ์ฒด ํƒ์ƒ‰
for obj in ObjectFinder("๋ฌธ์„œ.hwpx").find_all(tag="tbl"):
    print(obj.tag, obj.path)

๐ŸŽจ ์Šคํƒ€์ผ ๊ธฐ๋ฐ˜ ํ…์ŠคํŠธ ์น˜ํ™˜

์„œ์‹(์ƒ‰์ƒ, ๋ฐ‘์ค„, charPrIDRef)์œผ๋กœ ๋Ÿฐ์„ ํ•„ํ„ฐ๋งํ•ด ์„ ํƒ์ ์œผ๋กœ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค.

# ๋นจ๊ฐ„์ƒ‰ ํ…์ŠคํŠธ๋งŒ ์ฐพ์•„์„œ ์น˜ํ™˜
doc.replace_text_in_runs(
    "์ž„์‹œ", "ํ™•์ •",
    text_color="#FF0000",
)

# ํŠน์ • ์„œ์‹์˜ ๋Ÿฐ ๊ฒ€์ƒ‰
runs = doc.find_runs_by_style(underline_type="SINGLE")

๐Ÿ“ค ๋‚ด๋ณด๋‚ด๊ธฐ

# ํ…์ŠคํŠธ, HTML, Markdown์œผ๋กœ ๋ณ€ํ™˜
text = doc.export_text()
html = doc.export_html()
md   = doc.export_markdown()

๐Ÿ—๏ธ ์ €์ˆ˜์ค€ XML ์ œ์–ด

OWPML ์Šคํ‚ค๋งˆ์— ๋งคํ•‘๋œ ๋ฐ์ดํ„ฐํด๋ž˜์Šค๋กœ XML ๊ตฌ์กฐ๋ฅผ ์ง์ ‘ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

# ํ—ค๋” ์ฐธ์กฐ ๋ชฉ๋ก
doc.border_fills    # ํ…Œ๋‘๋ฆฌ ์ฑ„์šฐ๊ธฐ
doc.bullets         # ๊ธ€๋จธ๋ฆฌํ‘œ
doc.styles          # ์Šคํƒ€์ผ
doc.track_changes   # ๋ณ€๊ฒฝ ์ถ”์ 

# ๋ฐ”ํƒ•์ชฝยท์ด๋ ฅยท๋ฒ„์ „ ํŒŒํŠธ
doc.master_pages
doc.histories
doc.version

์•„ํ‚คํ…์ฒ˜

python-hwpx
โ”œโ”€โ”€ hwpx.document        # ๊ณ ์ˆ˜์ค€ ํŽธ์ง‘ API (HwpxDocument)
โ”œโ”€โ”€ hwpx.opc             # OPC ์ปจํ…Œ์ด๋„ˆ ์ฝ๊ธฐ/์“ฐ๊ธฐ (์›์ž์  ์ €์žฅ, ZIP ๋ฌด๊ฒฐ์„ฑ ๊ฒ€์ฆ)
โ”œโ”€โ”€ hwpx.oxml            # OWPML XML โ†” ๋ฐ์ดํ„ฐํด๋ž˜์Šค ๋งคํ•‘
โ”‚   โ”œโ”€โ”€ document.py      #   ์„น์…˜, ๋ฌธ๋‹จ, ํ‘œ, ๋Ÿฐ, ๋ฉ”๋ชจ, ๋„ํ˜•, ๋…ธํŠธ
โ”‚   โ”œโ”€โ”€ header.py        #   ํ—ค๋” ์ฐธ์กฐ ๋ชฉ๋ก (์Šคํƒ€์ผ, ๊ธ€๋จธ๋ฆฌํ‘œ, ๋ณ€๊ฒฝ์ถ”์  ๋“ฑ)
โ”‚   โ”œโ”€โ”€ body.py          #   ํƒ€์ž…์ด ์ง€์ •๋œ ๋ณธ๋ฌธ ๋ชจ๋ธ
โ”‚   โ””โ”€โ”€ common.py        #   ๋ฒ”์šฉ XML โ†” ๋ฐ์ดํ„ฐํด๋ž˜์Šค
โ”œโ”€โ”€ hwpx.tools
โ”‚   โ”œโ”€โ”€ archive_cli      #   unpack/pack CLI ๋ฐ ์žฌํŒจํ‚น ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
โ”‚   โ”œโ”€โ”€ text_extractor   #   ํ…์ŠคํŠธ ์ถ”์ถœ ํŒŒ์ดํ”„๋ผ์ธ
โ”‚   โ”œโ”€โ”€ text_extract_cli #   ํ…์ŠคํŠธ ์ถ”์ถœ CLI
โ”‚   โ”œโ”€โ”€ object_finder    #   ๊ฐ์ฒด ํƒ์ƒ‰ ์œ ํ‹ธ๋ฆฌํ‹ฐ
โ”‚   โ”œโ”€โ”€ exporter         #   ํ…์ŠคํŠธ/HTML/Markdown ๋‚ด๋ณด๋‚ด๊ธฐ
โ”‚   โ”œโ”€โ”€ validator        #   ์Šคํ‚ค๋งˆ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ (hwpx-validate CLI)
โ”‚   โ”œโ”€โ”€ package_validator#   ZIP/OPC/HWPX ๊ตฌ์กฐ ๊ฒ€์‚ฌ
โ”‚   โ”œโ”€โ”€ page_guard       #   ๊ตฌ์กฐ ๋ณ€ํ™” ์ง•ํ›„ ์ ๊ฒ€
โ”‚   โ””โ”€โ”€ template_analyzer#   ๋ ˆํผ๋Ÿฐ์Šค ๋ฌธ์„œ ๋ถ„์„/์ถ”์ถœ
โ””โ”€โ”€ hwpx.templates       # ๋‚ด์žฅ ๋นˆ ๋ฌธ์„œ ํ…œํ”Œ๋ฆฟ

CLI

# HWPX ๋ฌธ์„œ ์Šคํ‚ค๋งˆ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
hwpx-validate ๋ฌธ์„œ.hwpx

# ZIP/OPC/HWPX ํŒจํ‚ค์ง€ ๊ตฌ์กฐ ๊ฒ€์‚ฌ
hwpx-validate-package ๋ฌธ์„œ.hwpx

# HWPX ํ’€๊ธฐ / ๋‹ค์‹œ ๋ฌถ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: XML/HWPF ๋ฐ”์ดํŠธ ๋ณด์กด)
hwpx-unpack ๋ฌธ์„œ.hwpx ./unpacked
hwpx-unpack ๋ฌธ์„œ.hwpx ./pretty-unpacked --pretty-xml
hwpx-pack ./unpacked ./repacked.hwpx

# ๋ ˆํผ๋Ÿฐ์Šค ๋ฌธ์„œ ๋ถ„์„๊ณผ ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ ์ถ”์ถœ
hwpx-analyze-template ๋ฌธ์„œ.hwpx --extract-dir ./template-parts --json
hwpx-pack ./template-parts ./template-roundtrip.hwpx
hwpx-validate-package ./template-roundtrip.hwpx

# plain / markdown ํ…์ŠคํŠธ ์ถ”์ถœ
hwpx-text-extract ๋ฌธ์„œ.hwpx --format markdown --output ๋ฌธ์„œ.md

# ๋ฌธ์„œ ๊ตฌ์กฐ ๋ณ€ํ™” ์ง•ํ›„ ๋น„๊ต
hwpx-page-guard --reference ์›๋ณธ.hwpx --output ๊ฒฐ๊ณผ.hwpx

hwpx-page-guard๋Š” ๋ Œ๋”๋œ ์‹ค์ œ ์ชฝ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ๋‹จ๋ฝ ์ˆ˜, ํ‘œ ์ˆ˜, shape/control ์ˆ˜, ๋ช…์‹œ์  page/column break, ํ…์ŠคํŠธ ๊ธธ์ด ๊ฐ™์€ ๊ตฌ์กฐ ์ง€ํ‘œ๋ฅผ ๋น„๊ตํ•ด ํŽธ์ง‘ ์ „ํ›„ ๋ณ€ํ™” ์ง•ํ›„๋ฅผ ๋น ๋ฅด๊ฒŒ ์ ๊ฒ€ํ•ฉ๋‹ˆ๋‹ค.

hwpx-validate-package๋Š” Contents/content.hpf ๊ฐ™์€ ๊ณ ์ • ๊ฒฝ๋กœ๋ฅผ ์ „์ œ๋กœ ๋‘์ง€ ์•Š๊ณ , META-INF/container.xml๊ณผ ์‹ค์ œ rootfile/manifest ์„ ์–ธ์„ ๋”ฐ๋ผ๊ฐ€๋ฉฐ ํŒจํ‚ค์ง€ ๊ตฌ์กฐ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์—”์ง„์ด ์—ด ์ˆ˜ ์žˆ๋Š” ๋น„ํ‘œ์ค€ ํŒจํ‚ค์ง€๋Š” ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ๊ฒฝ๊ณ ๋กœ ๋ถ„๋ฆฌํ•ด ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

hwpx-analyze-template --extract-dir๋Š” ๋‹ค์‹œ ๋ฌถ๊ณ  ์ ๊ฒ€ํ•˜๊ธฐ ์‰ฌ์šด ์ž‘์—… ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์žฌ๊ตฌ์„ฑ๊ณผ ๊ตฌ์กฐ ๊ฒ€์ฆ์— ํ•„์š”ํ•œ ํŒŒ์ผ์„ ํ•จ๊ป˜ ๊บผ๋‚ด๋Š” ์šฉ๋„์ด๋ฉฐ, ํŽธ์ง‘๊ธฐ์—์„œ์˜ ์ตœ์ข… ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๊นŒ์ง€ ๋ณด์žฅํ•œ๋‹ค๋Š” ๋œป์€ ์•„๋‹™๋‹ˆ๋‹ค.

๋ฌธ์„œ

๐Ÿ“– ์ „์ฒด ๋ฌธ์„œ Sphinx ๊ธฐ๋ฐ˜ API ๋ ˆํผ๋Ÿฐ์Šค, ์‚ฌ์šฉ ๊ฐ€์ด๋“œ, FAQ
๐Ÿš€ ๋น ๋ฅธ ์‹œ์ž‘ 5๋ถ„ ์•ˆ์— HWPX ๋ฌธ์„œ ๋‹ค๋ฃจ๊ธฐ
๐Ÿ“š ์‚ฌ์šฉ ๊ฐ€์ด๋“œ 50+ ์‹ค์ „ ์‚ฌ์šฉ ํŒจํ„ด
๐Ÿ”ง API ๋ ˆํผ๋Ÿฐ์Šค ํด๋ž˜์Šคยท๋ฉ”์„œ๋“œ ์ƒ์„ธ ๋ช…์„ธ
๐Ÿ“ ์Šคํ‚ค๋งˆ ๊ฐœ์š” OWPML ์Šคํ‚ค๋งˆ ๊ตฌ์กฐ ์„ค๋ช…

์ง€์› ํฌ๋งท

ํฌ๋งท ํ™•์žฅ์ž ์ฝ๊ธฐ ์“ฐ๊ธฐ
HWPX .hwpx โœ… โœ…
HWP .hwp โŒ โŒ

Note: HWP(v5 ๋ฐ”์ด๋„ˆ๋ฆฌ) ํŒŒ์ผ์€ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•œ์ปด์˜คํ”ผ์Šค์—์„œ HWPX๋กœ ๋ณ€ํ™˜ ํ›„ ์‚ฌ์šฉํ•˜์„ธ์š”.

์š”๊ตฌ ์‚ฌํ•ญ

  • Python 3.10+
  • lxml โ‰ฅ 4.9

์•Œ๋ ค์ง„ ์ œ์•ฝ

  • add_shape() / add_control()์€ ํ•œ/๊ธ€์ด ์š”๊ตฌํ•˜๋Š” ๋ชจ๋“  ํ•˜์œ„ ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ณต์žกํ•œ ๊ฐœ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋Š” ํ•œ/๊ธ€์—์„œ ์—ด์–ด ๊ฒ€์ฆํ•ด ์ฃผ์„ธ์š”.
  • ์ด๋ฏธ์ง€ ์‚ฝ์ž… ์‹œ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ž„๋ฒ ๋“œ๋Š” ์ง€์›ํ•˜์ง€๋งŒ, <hp:pic> ์š”์†Œ์˜ ์™„์ „ํ•œ ์ž๋™ ์ƒ์„ฑ์€ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์•”ํ˜ธํ™”๋œ HWPX ํŒŒ์ผ์˜ ์•”๋ณตํ˜ธํ™”๋Š” ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ธฐ์—ฌํ•˜๊ธฐ

๋ฒ„๊ทธ ๋ฆฌํฌํŠธ, ๊ธฐ๋Šฅ ์ œ์•ˆ, PR ๋ชจ๋‘ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •๊ณผ ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•์€ CONTRIBUTING.md๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

git clone https://github.com/airmang/python-hwpx.git
cd python-hwpx
pip install -e ".[dev]"
pytest

License

Custom Non-Commercial License ยฉ python-hwpx Maintainers

Commercial use requires separate permission from the copyright holders.


Maintainer

Primary maintainer/contact: ๊ณ ๊ทœํ˜„ โ€” ๊ด‘๊ต๊ณ ๋“ฑํ•™๊ต ์ •๋ณดยท์ปดํ“จํ„ฐ ๊ต์‚ฌ

About

Pure Python HWPX automation: read, edit, generate, and validate documents without Hancom Office.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages