Skip to content

v0.18.0

Latest

Choose a tag to compare

@hwpforge-release-bot hwpforge-release-bot released this 25 Oct 21:49
· 14 commits to main since this release
Immutable release. Only release title and notes can be modified.
29af9b5

Changed (BREAKING)

  • cellยทstampยทstructural ํŽธ์ง‘๊ธฐ์˜ ์ž…๋ ฅ decode๋Š” DECODE_FAILED, no-op validateยทencodeยท์žฌdecode๋Š” INPUT_NOT_ROUNDTRIP_SAFE, ํŽธ์ง‘ ๋ฌธ์„œ ๊ฒ€์ฆ์€ VALIDATION_FAILED, ์ถœ๋ ฅ ์ƒ์„ฑ์€ ENCODE_FAILED, ์‚ฐ์ถœ๋ฌผ ๊ฒ€์ฆ์€ SELF_VERIFY_FAILED๋กœ ๋ถ„๋ฅ˜ํ•œ๋‹ค. ๋ณดํ˜ธ ํ•„๋“œ ์นจ๋ฒ”์€ PROTECTED_FIELD_RANGE, source-mapยทprovenance ๋ถˆ๋ณ€์‹์€ INTERNAL_INVARIANT๋‹ค. CLIยทMCPยทPython์ด ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • stamp์˜ delta ๊ฒ€์ฆ ์ฝ”๋“œ๋Š” SELF_VERIFY_FAILED, ๊ฐ™์€ ์…€ ์ค‘๋ณต ์ง€์ •์€ CELL_TARGET_DUPLICATE๋กœ ํ†ต์ผํ•œ๋‹ค.
  • CLI ์ข…๋ฃŒ ์ƒํƒœ๋Š” ๋ช…๋ น๊ณผ ๋น„๊ณต๊ฐœ typed ์ฝ”๋“œ๋กœ ๊ฒฐ์ •ํ•˜๋ฉฐ, ๊ฐ™์€ ๋ช…๋ นยท์ฝ”๋“œ์˜ ์ข…๋ฃŒ ๊ฐ’์€ ์˜ค๋ฅ˜ payload๋‚˜ ๋ฐœ์ƒ ๊ฒฝ๋กœ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€์ง€ ์•Š๋Š”๋‹ค. ์•„๋ž˜ ๋„ค ํŽธ์ง‘๊ธฐ ๋ณ€๊ฒฝ๊ตฐ๊ณผ ๋’ค์˜ I/O ๋‘ ๋ณ€๊ฒฝ๊ตฐ, validate ํ•œ ๋ณ€๊ฒฝ๊ตฐ(๋ชจ๋‘ ์ผ๊ณฑ ๋ณ€๊ฒฝ๊ตฐ)์„ ์ ์šฉํ•œ๋‹ค.
๋ช…๋ นยท์‹คํŒจ ์ด์ „ ์ข…๋ฃŒ 0.18 ์ข…๋ฃŒ
delete-paraยทinsert-para: no-op validateยทencodeยท์žฌdecode 2 1
stamp: no-op validateยทencodeยท์žฌdecode 2 1
set-cell: ์ž…๋ ฅ decodeยท์›๋ณธ ํŒจํ‚ค์ง€ ์ฝ๊ธฐ 1 2
delete-paraยทinsert-para: ์ถœ๋ ฅ decodeยท์‚ฐ์ถœ๋ฌผ ์ฝ๊ธฐยทfragment ํŒŒ์‹ฑ 2 1
  • Draft apply_set_cells ๊นŠ์ด ์ดˆ๊ณผ๋Š” CellEditError::NestingTooDeep { section: usize, reason }์ด๋ฉฐ Display๋Š” nesting depth exceeds the limit: {reason}๋‹ค. ๋ฐ”์ดํŠธ ์ž…๋ ฅ์€ decode ๊ด€๋ฌธ์—์„œ ๋จผ์ € ๊ฑฐ๋ถ€ํ•œ๋‹ค.

  • to_json ์€ ํŒŒ์„œ๋Š” ํ†ต๊ณผํ•˜์ง€๋งŒ Core ์ค‘์ฒฉ ๊นŠ์ด 32๋‹จ๊ณ„๋ฅผ ๋„˜๋Š” HWPX ์ž…๋ ฅ์—์„œ GRID_ADDR_PROJECTION_FAILED ๋Œ€์‹  ์ฝ๊ธฐ ๋‹จ๊ณ„์˜ DECODE_FAILED ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • stamp-plan ์€ ์ด์ „์— ์„ฑ๊ณตํ•˜๋˜ ๊ฐ™์€ ๊นŠ์ด ์ดˆ๊ณผ ์ž…๋ ฅ์„ ์ฝ๊ธฐ ๋‹จ๊ณ„์—์„œ DECODE_FAILED ๋กœ ๊ฑฐ๋ถ€ํ•œ๋‹ค.

  • fillยทstampยทinsert-paraยทdelete-paraยทset-cellยทpatch ๋Š” ๊ฐ™์€ ๊นŠ์ด ์ดˆ๊ณผ ์ž…๋ ฅ์—์„œ ์ด์ œ decode ๋‹จ๊ณ„์—์„œ ์‹คํŒจํ•˜๊ณ , ๋ฉ”์‹œ์ง€๋Š” Core error: ๋ฅผ ํฌํ•จํ•œ ๊นŠ์ด ์ดˆ๊ณผ ์ง„๋‹จ์œผ๋กœ ๋ฐ”๋€๋‹ค. ์—ฌ์„ฏ ํŽธ์ง‘๊ธฐ ๋ชจ๋‘ ์•„๋ž˜ ๋‹จ๊ณ„ ๋ถ„๋ฅ˜์— ๋”ฐ๋ผ DECODE_FAILED ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

  • CLIยทMCP๋Š” ๊ณตํ†ต OpsCode::as_str()๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. DECODE_ERROR, UNKNOWN_PRESET, INDEX_OUT_OF_RANGE ๋“ฑ์˜ ์ฐฝ๊ตฌ๋ณ„ ๋ณ„๋ช…์€ ์ œ๊ฑฐํ•œ๋‹ค. ์ •๋ฐ€ํ•œ ๊ธฐ์กด ๋„๋ฉ”์ธ ์ฝ”๋“œ์™€ ์˜๋ฏธ ์†์‹ค ์ฝ”๋“œ๋„ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•œ๋‹ค.

  • read์˜ ๊ตฌ์—ญยทํ‘œยทํ•„๋“œ ๋ถ€์žฌ๋Š” SECTION_OUT_OF_RANGE, TABLE_NOT_FOUND, FIELD_NOT_FOUND๋กœ ํ†ตํ•ฉํ•œ๋‹ค. ๊ด€๋ จ read variant 3๊ฐœ์™€ ์†Œ๋น„์ž๊ฐ€ ์—†์–ด์ง„ SectionWorkflowFailed, SetCellFailed, StampFailed, StructuralEditFailed ๋ฐ ์˜› lookup์„ ์‚ญ์ œํ•œ๋‹ค.

  • ์ž…๋ ฅ ๋ถ€์žฌ/๊ธฐํƒ€ ์ฝ๊ธฐ/ํฌ๊ธฐ ์ƒํ•œ/์ถœ๋ ฅ I/O๋Š” FILE_NOT_FOUND/FILE_READ_FAILED/INPUT_TOO_LARGE/FILE_WRITE_FAILED์ด๋‹ค. MCP ์ถœ๋ ฅ ๊ฒฝ๋กœ ์ •์ฑ… ๊ฑฐ๋ถ€๋Š” INVALID_OUTPUT_PATH์ด๋‹ค.

  • INVALID_SETยทDUPLICATE_SET๊ณผ ์ง„๋‹จ์šฉ ๋„ค ์ฝ”๋“œ, ์ด ์—ฌ์„ฏ CLI ์ „์šฉ ์ฝ”๋“œ๋Š” CLI ์•ˆ์—์„œ ์œ ์ง€ํ•œ๋‹ค. ์ž…๋ ฅ ๋ถ€์žฌยท์ฝ๊ธฐ ์‹คํŒจ๋Š” to-mdยทconvert-hwp5 2, ๋‚˜๋จธ์ง€ 1์ด๋ฉฐ ์ถœ๋ ฅ I/O๋Š” ๊ตฌ์กฐ ํŽธ์ง‘ยทconvert-hwp5 2, ๋‚˜๋จธ์ง€ 1์ด๋‹ค. INPUT_TOO_LARGE๋Š” ์ผ๋ฐ˜ ํŒŒ์ผ ์‚ฌ์ „ ๊ฒ€์‚ฌยทFIFO ๋ชจ๋‘ 1, convert-hwp5์˜ FILE_WRITE_FAILED๋Š” ์“ฐ๊ธฐยทํ›„์† stat ์‹คํŒจ ๋ชจ๋‘ 2์ด๋‹ค.

  • Python ํŒŒ์ผ I/O๋Š” HwpForgeError+OSError ๊ณ„์ธต๊ณผ ์ž…๋ ฅ ๋ถ€์žฌ ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ๊ด‘์—ญ catchยทOS ํ•„๋“œยทcopyยทpickle์„ ๋ณด์กดํ•˜๋ฉฐ ์ •ํ™•ํ•œ ํƒ€์ž… ๋น„๊ตยทPermissionError ํฌ์ฐฉ์—๋Š” ๋ณ€๊ฒฝ์ด ์žˆ๋‹ค. ๋ถ€๋ชจ ๋””๋ ‰ํ„ฐ๋ฆฌ๊ฐ€ ์—†๋Š” Document.save๋Š” FileNotFoundError ๋Œ€์‹  HwpForgeIOError๋กœ ํฌ์ฐฉํ•ด์•ผ ํ•œ๋‹ค.

  • to-pdfยทconvert-hwp5์˜ HWP5 ๋””์ฝ”๋“œ ์‹คํŒจ๋Š” HWP5_CONVERT_FAILED ๋Œ€์‹  HWP5_DECODE_FAILED๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. convert-hwp5 ์ถœ๋ ฅ ์“ฐ๊ธฐ ์‹คํŒจ๋Š” FILE_WRITE_FAILED, to-md ์ž…๋ ฅ ์‹คํŒจ๋Š” FILE_NOT_FOUNDยทFILE_READ_FAILEDยทINPUT_TOO_LARGE๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค. ์•„๋ž˜ ๋‘ I/O ๋ณ€๊ฒฝ๊ตฐ ์™ธ์˜ ์ข…๋ฃŒ ๊ฐ’์€ ์œ ์ง€ํ•œ๋‹ค.

  • MCP ์ง๋ ฌํ™” ์‹คํŒจ SERIALIZE_ERRORยทSTAMP_MANIFEST_SERIALIZE๋Š” JSON_SERIALIZE_FAILED๋กœ ํ†ตํ•ฉํ•œ๋‹ค.

  • CLI ๊ตฌ์กฐ ํŽธ์ง‘์˜ UNCARRIED_ZIP_ENTRIES๋Š” INPUT_ENTRIES_NOT_CARRIED, STRUCTURAL_EDIT_FAILED๋Š” ๊ตฌ์ฒด ๋„๋ฉ”์ธ ์ฝ”๋“œ ๋˜๋Š” UPSTREAM_UNMAPPED๋กœ ์ „๋‹ฌํ•œ๋‹ค.

  • set-cellยทstamp์˜ ์˜๋ฏธ ์†์‹ค์€ SET_CELL_CODEC_FAILEDยทSTAMP_CODEC_FAILED ๋Œ€์‹  ENCODE_SEMANTIC_LOSS์ด๋‹ค.

  • patchยทfill ์˜ ์˜ค๋ฅ˜๋ฅผ ์‹คํŒจ ๋‹จ๊ณ„์™€ ์›์ธ์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค. ์ž…๊ตฌ ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผํ•œ ๋’ค ์›๋ณธ์„ ์ฝ๊ฑฐ๋‚˜ decode ํ•˜์ง€ ๋ชปํ•˜๋ฉด PATCH_FAILEDยทFILL_FAILED ๋Œ€์‹  DECODE_FAILED ๋‹ค. ํŽธ์ง‘ํ•œ ๋ฌธ์„œ์˜ ๊ฒ€์ฆ ์‹คํŒจ๋Š” VALIDATION_FAILED, ์ถœ๋ ฅ ์ž‘์„ฑ ์‹คํŒจ๋Š” ENCODE_FAILED, ๋ณดํ˜ธ ํ•„๋“œ์˜ ๊ฐ’ยท๋ฒ”์œ„ ๋ณ€๊ฒฝ์€ PROTECTED_FIELD_RANGE, ๋‚ด๋ถ€ source mapยท์œ„์น˜ ๋ถˆ๋ณ€์‹ ํŒŒ์†์€ INTERNAL_INVARIANT ๋‹ค. PATCH_FAILED ๋Š” ๋ณด์กด patch ๊ฐ€ ๋ฐ›์ง€ ์•Š๋Š” ๋ณ€๊ฒฝ๊ณผ metadata ๋ถ€์žฌยท๋ถˆ์ผ์น˜์—๋งŒ, FILL_FAILED ๋Š” ํ•„๋“œ ๋ชฉ๋ก ์ง„๋‹จ์—๋งŒ ๋‚จ๋Š”๋‹ค.

  • fill ์€ ๋‚ด๋ถ€ patch ์˜ ์›์ธ์„ ๊ทธ๋Œ€๋กœ ์ „๋‹ฌํ•˜๋ฏ€๋กœ PATCH_FAILED ๋„ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค(์˜ˆ: ๋‹ค์‹œ ๋งŒ๋“ค ์ˆ˜ ์—†๋Š” ์ธ๋ผ์ธ ํ‘œ์ง€๊ฐ€ ๋“  ์นธ). ๊ฒ€์‚ฌ ์ˆœ์„œ๋Š” ๊ทธ๋Œ€๋กœ๋ผ metadata ๊ฐ€ ์—†๊ณ  XML ๋„ ์†์ƒ๋œ patch ๋Š” ๊ณ„์† PATCH_FAILED ๋‹ค. CLI ์ข…๋ฃŒ ๊ฐ’์€ ๋‘ ๋ช…๋ น ๋ชจ๋‘ ๋ฐ”๋€ ์ฝ”๋“œ์—์„œ๋„ ์ด์ „ PATCH_FAILEDยทFILL_FAILED ์™€ ๊ฐ™์€ 2 ๋‹ค(patch ์˜ ๊ตฌ์—ญ ๋ฒ”์œ„ ๊ฑฐ๋ถ€ SECTION_OUT_OF_RANGE 1 ์€ ๊ทธ๋Œ€๋กœ).

  • convert-hwp5ยทto-pdf(CLI)์™€ Python convert_hwp5ยทto_pdf ์˜ HWP5 ๋ณ€ํ™˜ ์‹คํŒจ๋„ ๋‹จ๊ณ„๋ณ„ ์ฝ”๋“œ๋ฅผ ๋‚ธ๋‹ค. ์ฝ์€ ๋ฌธ์„œ์˜ Core ๊ฒ€์ฆ ์‹คํŒจ๋Š” VALIDATION_FAILED, HWPX ์ถœ๋ ฅ ์ƒ์„ฑ ์‹คํŒจ๋Š” ENCODE_FAILED ์ด๊ณ , ๋””์ฝ”๋”๊ฐ€ ์Šค์Šค๋กœ ๊ฑฐ๋ถ€ํ•œ ์Šคํƒ€์ผยทํ…Œ๋‘๋ฆฌ ์ฐธ์กฐ(์˜ˆ: ์ •์˜๊ฐ€ ์—†๋Š” ํ‘œ ํ…Œ๋‘๋ฆฌ ๋ฒˆํ˜ธ)๋Š” HWP5_CONVERT_FAILED ๋Œ€์‹  HWP5_DECODE_FAILED ๋‹ค. HWP5_CONVERT_FAILED ๋Š” ์ƒ์„ฑํ•œ ํŒจํ‚ค์ง€์— ์ค„ ๋ฐฐ์น˜ ์ •๋ณด๋ฅผ ๋‹ค์‹œ ์ž…ํžˆ๋Š” ๋‹จ๊ณ„์—๋งŒ ๋‚จ๋Š”๋‹ค. ๋‘ CLI ๋ช…๋ น์˜ ์ข…๋ฃŒ ๊ฐ’์€ ๋ฐ”๋€ ์ฝ”๋“œ์—์„œ๋„ ์ด์ „๊ณผ ๊ฐ™์€ 2 ์ด๊ณ , ํžŒํŠธ๋„ ๊ทธ๋Œ€๋กœ๋‹ค. Python convert_hwp5ยทDocument.to_pdf ์—์„œ๋Š” ๋””์ฝ”๋”๊ฐ€ ๊ฑฐ๋ถ€ํ•œ ์ฐธ์กฐ์˜ ํžŒํŠธ๊ฐ€ ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผ Check that the source is a supported HWP5 document ์—์„œ Check that the file is a valid HWP5 document ๋กœ ๋ฐ”๋€๋‹ค(๊ฒ€์ฆยท์ถœ๋ ฅ ์ƒ์„ฑ ์‹คํŒจ์˜ ํžŒํŠธ๋Š” ๊ทธ๋Œ€๋กœ).

I/O์™€ validate์˜ ์ข…๋ฃŒ ๊ฐ’ ๋ณ€๊ฒฝ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. ํŽธ์ง‘๊ธฐ์˜ ๋„ค ๋ณ€๊ฒฝ๊ตฐ์€ ์œ„ ํ‘œ์— ์ ์—ˆ๋‹ค.

๋ช…๋ นยท์‹คํŒจ ์ด์ „ ์ฝ”๋“œยท์ข…๋ฃŒ 0.18 ์ฝ”๋“œยท์ข…๋ฃŒ
to-mdยทconvert-hwp5์˜ ํฌ๊ธฐ ํ•œ๋„๋ฅผ ๋„˜๋Š” FIFO ์ž…๋ ฅ DECODE_FAILEDยทHWP5_DECODE_FAILED / 2 INPUT_TOO_LARGE / 1
convert-hwp5์˜ ์“ฐ๊ธฐ ์„ฑ๊ณต ์งํ›„ stat ์‹คํŒจ FILE_WRITE_FAILED / 1 FILE_WRITE_FAILED / 2
validate: ํŒŒ์„œ๋Š” ํ†ต๊ณผํ•˜๊ณ  Core ์ค‘์ฒฉ ๊นŠ์ด๊ฐ€ 32 ๋ฅผ ๋„˜๋Š” HWPX ํŒ์ •(valid:false) / 3 DECODE_FAILED / 2
  • validate ๋Š” ํŒŒ์„œ๋Š” ํ†ต๊ณผํ•˜์ง€๋งŒ Core ์ค‘์ฒฉ ๊นŠ์ด๊ฐ€ 32 ๋ฅผ ๋„˜๋Š” HWPX ์—์„œ ํŒ์ •(valid:false) ๋Œ€์‹  DECODE_FAILED ๋กœ ์‹คํŒจํ•œ๋‹ค. HWPX decode ์ง„์ž…์ ์ด ์ด ๊นŠ์ด๋ฅผ ๊ฑฐ๋ถ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋ฉฐ(์˜ค๋ฅ˜ E4008), ํŒŒ์„œ ํ•œ๋„(ํ‘œ ์ค‘์ฒฉยทXML ์˜ˆ์‚ฐ)์— ๊ฑธ๋ฆฐ ๋ฌธ์„œ๋Š” 0.17.1 ์—์„œ๋„ DECODE_FAILED ์˜€์œผ๋ฏ€๋กœ ๊ทธ๋Œ€๋กœ๋‹ค. ์ดํ–‰: Rust ops ์˜ validate ๋Š” Ok(ValidateOutput { ok: false, .. }) ๋Œ€์‹  Err ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , MCP hwpforge_validate ๋Š” valid:false ๋ฐ์ดํ„ฐ ๋Œ€์‹  ๋„๊ตฌ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, Python Document.validate() ๋Š” ok: False ๋ฅผ ๋Œ๋ ค์ฃผ์ง€ ์•Š๊ณ  ์ฝ”๋“œ DECODE_FAILED ์˜ HwpForgeError ๋ฅผ ์ผ์œผํ‚จ๋‹ค. CLI ๋Š” stdout ํŒ์ •๊ณผ ์ข…๋ฃŒ 3 ๋Œ€์‹  stderr ์˜ DECODE_FAILED ์™€ ์ข…๋ฃŒ 2 ๋ฅผ ๋‚ธ๋‹ค. ๊นŠ์ด ์ดˆ๊ณผ๋ฅผ ํŒ์ •์œผ๋กœ ๋ฐ›๋˜ ํ˜ธ์ถœ๋ถ€๋Š” ์˜ค๋ฅ˜ ๊ฒฝ๋กœ์—์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • HWPX์—์„œ ์ฝ์€ ๋ณธ๋ฌธ์˜ CR์ด \r ๋Œ€์‹  \n์œผ๋กœ ๋‚˜์˜จ๋‹ค(to-json, Python, MCP, ๋ฌด์†์‹ค Markdown). ์ดํ–‰: \r์— ๊ธฐ๋Œ€๋˜ ์ฝ”๋“œ๋ฅผ ๊ณ ์น˜๊ณ , 0.17์—์„œ ๋‚ด๋ณด๋‚ธ ๋ณด์กด metadata ์ค‘ CR์ด ๋“  ์นธ์ด ์žˆ์œผ๋ฉด ๋‹ค์‹œ ๋‚ด๋ณด๋‚ธ ๋’ค patchํ•œ๋‹ค. ์ž์„ธํ•œ ๊ฒƒ์€ hwpforge-smithy-hwpx ํ•ญ๋ชฉ์„ ๋ณธ๋‹ค.

Changed

  • hwpforge-* ํฌ๋ ˆ์ดํŠธ๋ผ๋ฆฌ์˜ ์˜์กด ์š”๊ตฌ๊ฐ€ "0"(0.x ์•„๋ฌด ๋ฒ„์ „) ๋Œ€์‹  ๋ฆด๋ฆฌ์Šค ๋ฒ„์ „(์˜ˆ: "0.18.0")์„ ์ตœ์†Œ ๋ฒ„์ „์œผ๋กœ ์š”๊ตฌํ•œ๋‹ค. ๊ทธ๋ž˜์„œ cargo ๊ฐ€ ์ด ์˜์กด์— ๋‹ค๋ฅธ hwpforge-* ํฌ๋ ˆ์ดํŠธ์˜ ์ด์ „ minor ๋ฅผ ๊ณ ๋ฅด์ง€ ์•Š๋Š”๋‹ค. hwpforge-* ๋ฅผ ์ง์ ‘ ์—ฌ๋Ÿฌ ๊ฐœ ์˜์กดํ•œ๋‹ค๋ฉด ํ•จ๊ป˜ ์˜ฌ๋ฆฐ๋‹ค.
  • INPUT_NOT_ROUNDTRIP_SAFE ํžŒํŠธ๋Š” ์ฝ”๋ฑ ๊ฐญ ์ˆ˜์ • ๋Œ€๊ธฐ ์•ˆ๋‚ด ๋Œ€์‹  ์›๋ณธ์„ ๋ณด์กดํ•˜๋Š” ํ…์ŠคํŠธ to-json(section) โ†’ patchยท๋ˆ„๋ฆ„ํ‹€ fill ๊ฒฝ๋กœ๋ฅผ ์•ˆ๋‚ดํ•œ๋‹ค. MCP stamp๋„ ํ•ด๋‹น ๋„๊ตฌ ์ด๋ฆ„์œผ๋กœ ๊ฐ™์€ ์•ˆ๋‚ด๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

Fixed

  • convert(CLIยทMCPยทPython convert_md)๊ฐ€ Markdown ์˜ ๋Œ€์ƒ์ด ๋นˆ ์ด๋ฏธ์ง€(![x]())๋ฅผ 0.17.0 ์ฒ˜๋Ÿผ IMAGE_EMBED_SKIPPED ๊ฒฝ๊ณ ์™€ ํ•จ๊ป˜ ๋บ€๋‹ค. 0.17.1 ์—์„œ๋Š” ๊ฒฝ๊ณ  ์—†์ด 50ร—30mm ๋นˆ ๊ทธ๋ฆผ ํ‹€๋กœ ๋‚จ์•˜๋‹ค. ํ•œ์ปด์ด ์ž์‚ฐ์„ ์žƒ์€ ์ฑ„ ์ €์žฅํ•œ ๊ทธ๋ฆผ ํ‹€(#266)์€ ๊ทธ๋Œ€๋กœ ๋‚จ๋Š”๋‹ค.
  • HWPX ๊ตฌ์—ญ(<hs:sec>) ๋ฐ”๋กœ ์•„๋ž˜์— ๋†“์—ฌ ์ฝ์ง€ ๋ชปํ•˜๋Š” ๊ธ€ยท์š”์†Œยท<hp:t> ๋ฅผ CONTENT_LOST (section_content) ๊ฒฝ๊ณ ๋กœ ์•Œ๋ฆฌ๊ณ , restyleยทset-cellยทstamp ๋Š” ๊ทธ๋Ÿฐ ๋ฌธ์„œ๋ฅผ ๊ฑฐ๋ถ€ํ•œ๋‹ค. ์ „์—๋Š” ๊ฒฝ๊ณ  ์—†์ด ๊ทธ ๊ธ€์„ ๋บ๋‹ค. ์ž์„ธํ•œ ๊ฒƒ์€ hwpforge-smithy-hwpx ํ•ญ๋ชฉ์„ ๋ณธ๋‹ค.
  • HWP ๋ฌถ์Œ ์•ˆ ๊ทธ๋ฆผ์˜ ํ…Œ๋‘๋ฆฌ ์†์‹ค ๊ฒฝ๊ณ ๊ฐ€ ์†์‹ค์„ ํŒ์ •ํ•œ ์„  ์ข…๋ฅ˜๋ฅผ ํ•จ๊ป˜ ์ ๋Š”๋‹ค(border: line type 2, thickness 0). ์ „์—๋Š” ๋‘๊ป˜๋งŒ ์ ์–ด, ๋‘๊ป˜ 0 ์ธ ํ…Œ๋‘๋ฆฌ๊ฐ€ ์™œ ์†์‹ค์ธ์ง€ ๋ณด์ด์ง€ ์•Š์•˜๋‹ค(#256 ํ›„์†).

์—…๊ทธ๋ ˆ์ด๋“œ ์ฃผ์˜

  • HWP ๋ณ€ํ™˜์˜ ๊นŠ์ด ์ดˆ๊ณผ: HWP5 ๋””์ฝ”๋”๋Š” ์ปจํ…Œ์ด๋„ˆ๋งˆ๋‹ค ๊นŠ์ด๋ฅผ 1์”ฉ ์„ธ์–ด 32์—์„œ ๋ฉˆ์ถ”์ง€๋งŒ Core ๋Š” ์บก์…˜ยท๋ฌถ์Œ ์•ˆ ๋„ํ˜•์„ ํ•œ ๊ฒน์— 2 ์ด์ƒ์œผ๋กœ ์„ผ๋‹ค. ๊ทธ๋ž˜์„œ ๋””์ฝ”๋” ์ƒํ•œ ์•ˆ์˜ HWP ๋ฌธ์„œ๋„ Core ๊นŠ์ด 32๋‹จ๊ณ„๋ฅผ ๋„˜์œผ๋ฉด convert-hwp5ยทto-pdf ์™€ Python convert_hwp5 ๊ฐ€ VALIDATION_FAILED ๋กœ ์‹คํŒจํ•  ์ˆ˜ ์žˆ๋‹ค. 0.17.1 ์˜ ๊นŠ์ด ํ•œ๋„(#267)๊ฐ€ HWP ๋ณ€ํ™˜์—๋„ ๊ฑธ๋ฆฐ๋‹ค๋Š” ๋œป์ด๋‹ค. ์‹ค์ œ HWP ๋ฌธ์„œ์—์„œ ์ด๋ ‡๊ฒŒ ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์ธก์ •ํ•˜์ง€ ์•Š์•˜๋‹ค.
  • ์Šคํ‚ฌ ์œ„์น˜ (#270, 0.17.1): ์ €์žฅ์†Œ์˜ ์—์ด์ „ํŠธ ์Šคํ‚ฌ์ด .claude/skills/ ์—์„œ skills/ ๋กœ ์˜ฎ๊ฒจ์กŒ๋‹ค. 0.17.1 CHANGELOG ์— ๋น ์กŒ๋˜ ํ•ญ๋ชฉ์ด๋‹ค.