kordoc 4.9.0 → 4.9.2

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 (122) hide show
  1. package/README.md +16 -0
  2. package/dist/{-GCDZVN36.js → -Z4LCTGQR.js} +14 -8
  3. package/dist/{chunk-VVMXAB5N.js → chunk-5ZPXRDS2.js} +2 -2
  4. package/dist/{chunk-GLVZNMMN.js → chunk-6WYMV73J.js} +304 -27
  5. package/dist/chunk-6WYMV73J.js.map +1 -0
  6. package/dist/{chunk-BANRDDJL.cjs → chunk-BAJVZXC7.cjs} +3 -3
  7. package/dist/chunk-BAJVZXC7.cjs.map +1 -0
  8. package/dist/chunk-DCZVOIEO.cjs.map +1 -1
  9. package/dist/{chunk-XLARMJAD.js → chunk-GL6BCNJV.js} +3 -3
  10. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  11. package/dist/{chunk-L6VNNUV4.js → chunk-JHPEDWJX.js} +3 -3
  12. package/dist/{chunk-5Y7WKVVP.cjs → chunk-KATZTHWA.cjs} +2 -2
  13. package/dist/chunk-KATZTHWA.cjs.map +1 -0
  14. package/dist/chunk-L5CDTOC3.cjs.map +1 -1
  15. package/dist/{chunk-MQKK34ID.js → chunk-LJP3PK2S.js} +2 -2
  16. package/dist/{chunk-SKTYYRUD.js → chunk-LKZQ4564.js} +2 -2
  17. package/dist/{chunk-EPPJTZJJ.js → chunk-LREEDIEF.js} +2 -2
  18. package/dist/{chunk-YQ3EWPCN.js → chunk-LUY46O7O.js} +2 -2
  19. package/dist/{chunk-CTOIJPOZ.js → chunk-NIBRVLGS.js} +2 -2
  20. package/dist/{chunk-4ZHZL44G.cjs → chunk-NIQ4JCQF.cjs} +6 -6
  21. package/dist/chunk-NIQ4JCQF.cjs.map +1 -0
  22. package/dist/{chunk-THB2RO2P.js → chunk-NOEYLJGJ.js} +3 -3
  23. package/dist/{chunk-IJH3NEF3.js → chunk-OOT54JF2.js} +2 -2
  24. package/dist/{chunk-KWKYWCPR.js → chunk-OYQL3D4B.js} +2 -2
  25. package/dist/{chunk-MRFUIWOD.js → chunk-PIUPP3FL.js} +3 -3
  26. package/dist/{chunk-WBVORBGM.js → chunk-PKCDYIIJ.js} +2 -2
  27. package/dist/{chunk-ZL5R3O5Y.cjs → chunk-SHBVD23C.cjs} +7 -7
  28. package/dist/chunk-SHBVD23C.cjs.map +1 -0
  29. package/dist/{chunk-K4JVORUT.js → chunk-TK7WUS47.js} +2 -2
  30. package/dist/{chunk-BK6ZFFZO.cjs → chunk-V3Q6I2AQ.cjs} +4 -4
  31. package/dist/chunk-V3Q6I2AQ.cjs.map +1 -0
  32. package/dist/{chunk-YZWSTDT7.js → chunk-VYGNPB2X.js} +2 -2
  33. package/dist/{chunk-PPA3BSEX.js → chunk-WLZX2HTC.js} +2 -2
  34. package/dist/{chunk-4DEU3YJR.js → chunk-Y7QB4IB6.js} +2 -2
  35. package/dist/chunks-TRJGNO4N.js +10 -0
  36. package/dist/cli.js +47 -25
  37. package/dist/cli.js.map +1 -1
  38. package/dist/{formula-IIF334U5.js → formula-77TJPACH.js} +3 -3
  39. package/dist/{formula-W35NSRS5.cjs → formula-JVBJ6QRG.cjs} +9 -9
  40. package/dist/formula-JVBJ6QRG.cjs.map +1 -0
  41. package/dist/{formula-W6VEVOGF.js → formula-LFWZG7T7.js} +4 -4
  42. package/dist/{image-ocr-KCH5UMWN.js → image-ocr-6SY623KL.js} +7 -7
  43. package/dist/{image-ocr-ZR2HP4WG.cjs → image-ocr-YTGAUHEP.cjs} +11 -11
  44. package/dist/image-ocr-YTGAUHEP.cjs.map +1 -0
  45. package/dist/{image-ocr-4CF6B2ZP.js → image-ocr-YZ56O63S.js} +5 -5
  46. package/dist/index.cjs +471 -194
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +46 -1
  49. package/dist/index.d.ts +46 -1
  50. package/dist/index.js +300 -23
  51. package/dist/index.js.map +1 -1
  52. package/dist/mcp.js +19 -16
  53. package/dist/mcp.js.map +1 -1
  54. package/dist/{model-bundle-ZIHP5ULR.js → model-bundle-W7B3BIYS.js} +5 -5
  55. package/dist/{models-Q7HDRZMF.js → models-FUKPEVPE.js} +5 -5
  56. package/dist/page-range-P7SDW6LR.cjs.map +1 -1
  57. package/dist/{parser-O3X37357.js → parser-6UL2HLDH.js} +6 -6
  58. package/dist/{parser-SPK4QG4F.js → parser-GDYZDBZI.js} +6 -6
  59. package/dist/{parser-7HS5FORY.cjs → parser-WIRWVN5E.cjs} +26 -26
  60. package/dist/parser-WIRWVN5E.cjs.map +1 -0
  61. package/dist/pdf-ocr-O373AAN6.cjs +14 -0
  62. package/dist/pdf-ocr-O373AAN6.cjs.map +1 -0
  63. package/dist/pdf-ocr-OHUAQQMN.js +16 -0
  64. package/dist/pdf-ocr-XTE234WC.js +13 -0
  65. package/dist/{profile-io-PQSH3EPJ.js → profile-io-4EE64K6Y.js} +3 -3
  66. package/dist/{rasterize-NMCA7XRR.js → rasterize-QW7SSKHB.js} +2 -2
  67. package/dist/render-2NID54BX.js +10 -0
  68. package/dist/seal-PTP4TWYR.js +10 -0
  69. package/dist/{setup-CQ6SMNMA.js → setup-JS7E2HFM.js} +3 -3
  70. package/dist/{watch-4BOS6J6K.js → watch-YISVPGW3.js} +9 -9
  71. package/package.json +1 -1
  72. package/dist/chunk-4ZHZL44G.cjs.map +0 -1
  73. package/dist/chunk-5Y7WKVVP.cjs.map +0 -1
  74. package/dist/chunk-BANRDDJL.cjs.map +0 -1
  75. package/dist/chunk-BK6ZFFZO.cjs.map +0 -1
  76. package/dist/chunk-GLVZNMMN.js.map +0 -1
  77. package/dist/chunk-ZL5R3O5Y.cjs.map +0 -1
  78. package/dist/chunks-R6PFU6OR.js +0 -10
  79. package/dist/formula-W35NSRS5.cjs.map +0 -1
  80. package/dist/image-ocr-ZR2HP4WG.cjs.map +0 -1
  81. package/dist/parser-7HS5FORY.cjs.map +0 -1
  82. package/dist/pdf-ocr-4XUES6M5.js +0 -16
  83. package/dist/pdf-ocr-6D7OPO2X.cjs +0 -14
  84. package/dist/pdf-ocr-6D7OPO2X.cjs.map +0 -1
  85. package/dist/pdf-ocr-NICPW5HS.js +0 -13
  86. package/dist/render-MMAQI7DM.js +0 -10
  87. package/dist/seal-GWABZNEC.js +0 -10
  88. /package/dist/{-GCDZVN36.js.map → -Z4LCTGQR.js.map} +0 -0
  89. /package/dist/{chunk-VVMXAB5N.js.map → chunk-5ZPXRDS2.js.map} +0 -0
  90. /package/dist/{chunk-XLARMJAD.js.map → chunk-GL6BCNJV.js.map} +0 -0
  91. /package/dist/{chunk-L6VNNUV4.js.map → chunk-JHPEDWJX.js.map} +0 -0
  92. /package/dist/{chunk-MQKK34ID.js.map → chunk-LJP3PK2S.js.map} +0 -0
  93. /package/dist/{chunk-SKTYYRUD.js.map → chunk-LKZQ4564.js.map} +0 -0
  94. /package/dist/{chunk-EPPJTZJJ.js.map → chunk-LREEDIEF.js.map} +0 -0
  95. /package/dist/{chunk-YQ3EWPCN.js.map → chunk-LUY46O7O.js.map} +0 -0
  96. /package/dist/{chunk-CTOIJPOZ.js.map → chunk-NIBRVLGS.js.map} +0 -0
  97. /package/dist/{chunk-THB2RO2P.js.map → chunk-NOEYLJGJ.js.map} +0 -0
  98. /package/dist/{chunk-IJH3NEF3.js.map → chunk-OOT54JF2.js.map} +0 -0
  99. /package/dist/{chunk-KWKYWCPR.js.map → chunk-OYQL3D4B.js.map} +0 -0
  100. /package/dist/{chunk-MRFUIWOD.js.map → chunk-PIUPP3FL.js.map} +0 -0
  101. /package/dist/{chunk-WBVORBGM.js.map → chunk-PKCDYIIJ.js.map} +0 -0
  102. /package/dist/{chunk-K4JVORUT.js.map → chunk-TK7WUS47.js.map} +0 -0
  103. /package/dist/{chunk-YZWSTDT7.js.map → chunk-VYGNPB2X.js.map} +0 -0
  104. /package/dist/{chunk-PPA3BSEX.js.map → chunk-WLZX2HTC.js.map} +0 -0
  105. /package/dist/{chunk-4DEU3YJR.js.map → chunk-Y7QB4IB6.js.map} +0 -0
  106. /package/dist/{chunks-R6PFU6OR.js.map → chunks-TRJGNO4N.js.map} +0 -0
  107. /package/dist/{formula-IIF334U5.js.map → formula-77TJPACH.js.map} +0 -0
  108. /package/dist/{formula-W6VEVOGF.js.map → formula-LFWZG7T7.js.map} +0 -0
  109. /package/dist/{image-ocr-KCH5UMWN.js.map → image-ocr-6SY623KL.js.map} +0 -0
  110. /package/dist/{image-ocr-4CF6B2ZP.js.map → image-ocr-YZ56O63S.js.map} +0 -0
  111. /package/dist/{model-bundle-ZIHP5ULR.js.map → model-bundle-W7B3BIYS.js.map} +0 -0
  112. /package/dist/{models-Q7HDRZMF.js.map → models-FUKPEVPE.js.map} +0 -0
  113. /package/dist/{parser-O3X37357.js.map → parser-6UL2HLDH.js.map} +0 -0
  114. /package/dist/{parser-SPK4QG4F.js.map → parser-GDYZDBZI.js.map} +0 -0
  115. /package/dist/{pdf-ocr-4XUES6M5.js.map → pdf-ocr-OHUAQQMN.js.map} +0 -0
  116. /package/dist/{pdf-ocr-NICPW5HS.js.map → pdf-ocr-XTE234WC.js.map} +0 -0
  117. /package/dist/{profile-io-PQSH3EPJ.js.map → profile-io-4EE64K6Y.js.map} +0 -0
  118. /package/dist/{rasterize-NMCA7XRR.js.map → rasterize-QW7SSKHB.js.map} +0 -0
  119. /package/dist/{render-MMAQI7DM.js.map → render-2NID54BX.js.map} +0 -0
  120. /package/dist/{seal-GWABZNEC.js.map → seal-PTP4TWYR.js.map} +0 -0
  121. /package/dist/{setup-CQ6SMNMA.js.map → setup-JS7E2HFM.js.map} +0 -0
  122. /package/dist/{watch-4BOS6J6K.js.map → watch-YISVPGW3.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -1168,6 +1168,51 @@ declare function lintGongmunText(text: string): GongmunLintFinding[];
1168
1168
  /** 검수 결과를 사람이 읽는 경고 문자열 배열로 — generate 경고 채널(A2와 동일)용 */
1169
1169
  declare function gongmunLintWarnings(text: string, limit?: number): string[];
1170
1170
 
1171
+ /**
1172
+ * 개조식 보고서 문체 검수기 — 서식이 맞아도 문체가 다르면 그 부서 문서로 읽히지 않는다.
1173
+ *
1174
+ * 표기법 검수(gongmun-lint.ts)가 "어떻게 적는가"를 본다면 이 모듈은 "어떤 꼴로 끝나는가"를
1175
+ * 본다. 개조식은 서술형 문장이 아니라 명사구로 끝나는 짧은 줄을 층층이 쌓는 문체다.
1176
+ *
1177
+ * 근거: 지자체 실무부서의 요약보고·기본계획·검토보고 15건(2,288줄) 실측 통계 —
1178
+ * jkf87/hwpx-skill v1.17.0 이 references/bogo-munche.md 로 공개한 수치를 임계값 근거로
1179
+ * 삼았다(서술형 `~다` 종결 0/264 항목, 항목 중앙 31자, 결론 중앙 30자, 물음표·느낌표
1180
+ * 본문 0건). 규칙 코드·정규식·판정 로직은 kordoc 자체 구현이다.
1181
+ *
1182
+ * 범위: 검수는 조언용이다 — 생성은 막지 않고 경고만 낸다(표기법 검수·폰트 경고와 같은
1183
+ * 원칙). 문체 *변환*은 여전히 엔진 범위 밖이다(gongmunseo-engine-spec.md).
1184
+ * 상세 규칙과 예문은 docs/gaejosik-munche.md.
1185
+ */
1186
+ interface MuncheLintFinding {
1187
+ /** 1-based 줄 번호 */
1188
+ line: number;
1189
+ /** 걸린 원문 조각 */
1190
+ match: string;
1191
+ /** 규칙 코드 (DA_ENDING 등) */
1192
+ rule: string;
1193
+ severity: "error" | "warning";
1194
+ /** 판정된 줄 종류 — 같은 문장도 층에 따라 허용 여부가 다르다 */
1195
+ kind: MuncheLineKind;
1196
+ message: string;
1197
+ suggest?: string;
1198
+ }
1199
+ /**
1200
+ * 개조식 문체를 쓰는 프리셋 — 보고서·계획서·개조식보고서.
1201
+ * 기안문·시행문(official)은 경어 종결(`~하시기 바랍니다`), 통지·회의록·보도자료도
1202
+ * 각기 다른 문체 관행이라 이 검수를 적용하지 않는다. 적용 범위를 좁히는 것이
1203
+ * 오탐을 막는 가장 확실한 수단이다.
1204
+ */
1205
+ declare function usesGaejosikMunche(preset?: string): boolean;
1206
+ /** □ 소제목 / ❍ 항목 / - 세부 / ⇒ 결론 / > 리드문 / ※ 참고 / 그 밖 */
1207
+ type MuncheLineKind = "dae" | "item" | "sub" | "concl" | "lead" | "note" | "para";
1208
+ /**
1209
+ * 원고(마크다운/텍스트) 문체 검수. 코드펜스 안은 건너뛴다 — 예시 코드가 종결·대조
1210
+ * 규칙에 오탐되는 것 방지(표기법 검수와 같은 원칙).
1211
+ */
1212
+ declare function lintMuncheText(text: string): MuncheLintFinding[];
1213
+ /** 검수 결과를 사람이 읽는 경고 문자열 배열로 — generate 경고 채널(표기법과 동일)용 */
1214
+ declare function muncheLintWarnings(text: string, limit?: number): string[];
1215
+
1171
1216
  /**
1172
1217
  * 한글 조판 텍스트 폭 계산 — 함초롬바탕(HCR Batang) 실측 advance 테이블
1173
1218
  *
@@ -1863,4 +1908,4 @@ interface FillFormOutput {
1863
1908
  */
1864
1909
  declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillInput>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1865
1910
 
1866
- export { BUILTIN_TEMPLATES, type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type BuiltinTemplate, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type ChunkOptions, type ClickHereField, DEFAULT_REDACT_RULES, type DiffChangeType, type DiffResult, type DocChunk, type DocumentMetadata, type DocumentQualitySummary, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillInput, type FillOutputFormat, type FillResult, type FillValue, type FormField, type FormFieldSchema, type FormFieldType, type FormResult, type FormSchemaResult, type FormatProfile, type GongmunFont, type GongmunLintFinding, type GongmunNumbering, type GongmunOptions, type GongmunPreset, type GongmunPresetInput, type HwpxFillResult, HwpxSession, type HwpxTheme, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type MarkdownToHwpxOptions, type MeasureOptions, type OcrProvider, type OutlineItem, PRESET_ALIAS, type PageMargin, type PageMarkdown, type PageOptions, type PageQuality, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PatchOptions, type PatchResult, type PatchSkip, type PlaceSealResult, type PrintOptions, type PrintPreset, type RedactHit, type RedactOptions, type RedactRule, type RedactTextResult, type RenderSvgOptions, type RenderSvgResult, SPACE_EM_FIXED, SPACE_EM_FONT, type ScanCell, type ScanParaKind, type ScanParagraph, type ScanTable, type SealOp, type SealPlacement, type SectionScan, type SpliceEdit, type TRange, type TableProfile, VERSION, type ValidateIssue, type ValidateResult, ValueCursor, type WarningCode, type WatchOptions, type WrapMode, type WrapResult, applySplices, blocksToChunks, blocksToMarkdown, blocksToPages, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractClickHereFields, extractFormFields, extractFormSchema, fillForm, fillFormFields, fillHwpx, fillWithUniqueGuard, fitRatioForFewerLines, formatFillValue, gongmunLintWarnings, hwpxToProfile, incompatibleGongmunWarnings, inferFieldType, isHwpxFile, isKnownFont, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, lintGongmunText, markdownToHwpx, markdownToPdf, measureTextWidth, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parseImage, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, readBuiltinTemplate, readBuiltinTemplateSample, redactMarkdown, redactText, renderHtml, renderHwpxToSvg, resolveBuiltinTemplate, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, validateHwpx };
1911
+ export { BUILTIN_TEMPLATES, type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type BuiltinTemplate, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type ChunkOptions, type ClickHereField, DEFAULT_REDACT_RULES, type DiffChangeType, type DiffResult, type DocChunk, type DocumentMetadata, type DocumentQualitySummary, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillInput, type FillOutputFormat, type FillResult, type FillValue, type FormField, type FormFieldSchema, type FormFieldType, type FormResult, type FormSchemaResult, type FormatProfile, type GongmunFont, type GongmunLintFinding, type GongmunNumbering, type GongmunOptions, type GongmunPreset, type GongmunPresetInput, type HwpxFillResult, HwpxSession, type HwpxTheme, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type MarkdownToHwpxOptions, type MeasureOptions, type MuncheLineKind, type MuncheLintFinding, type OcrProvider, type OutlineItem, PRESET_ALIAS, type PageMargin, type PageMarkdown, type PageOptions, type PageQuality, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PatchOptions, type PatchResult, type PatchSkip, type PlaceSealResult, type PrintOptions, type PrintPreset, type RedactHit, type RedactOptions, type RedactRule, type RedactTextResult, type RenderSvgOptions, type RenderSvgResult, SPACE_EM_FIXED, SPACE_EM_FONT, type ScanCell, type ScanParaKind, type ScanParagraph, type ScanTable, type SealOp, type SealPlacement, type SectionScan, type SpliceEdit, type TRange, type TableProfile, VERSION, type ValidateIssue, type ValidateResult, ValueCursor, type WarningCode, type WatchOptions, type WrapMode, type WrapResult, applySplices, blocksToChunks, blocksToMarkdown, blocksToPages, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractClickHereFields, extractFormFields, extractFormSchema, fillForm, fillFormFields, fillHwpx, fillWithUniqueGuard, fitRatioForFewerLines, formatFillValue, gongmunLintWarnings, hwpxToProfile, incompatibleGongmunWarnings, inferFieldType, isHwpxFile, isKnownFont, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, lintGongmunText, lintMuncheText, markdownToHwpx, markdownToPdf, measureTextWidth, muncheLintWarnings, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parseImage, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, readBuiltinTemplate, readBuiltinTemplateSample, redactMarkdown, redactText, renderHtml, renderHwpxToSvg, resolveBuiltinTemplate, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, usesGaejosikMunche, validateHwpx };
package/dist/index.d.ts CHANGED
@@ -1168,6 +1168,51 @@ declare function lintGongmunText(text: string): GongmunLintFinding[];
1168
1168
  /** 검수 결과를 사람이 읽는 경고 문자열 배열로 — generate 경고 채널(A2와 동일)용 */
1169
1169
  declare function gongmunLintWarnings(text: string, limit?: number): string[];
1170
1170
 
1171
+ /**
1172
+ * 개조식 보고서 문체 검수기 — 서식이 맞아도 문체가 다르면 그 부서 문서로 읽히지 않는다.
1173
+ *
1174
+ * 표기법 검수(gongmun-lint.ts)가 "어떻게 적는가"를 본다면 이 모듈은 "어떤 꼴로 끝나는가"를
1175
+ * 본다. 개조식은 서술형 문장이 아니라 명사구로 끝나는 짧은 줄을 층층이 쌓는 문체다.
1176
+ *
1177
+ * 근거: 지자체 실무부서의 요약보고·기본계획·검토보고 15건(2,288줄) 실측 통계 —
1178
+ * jkf87/hwpx-skill v1.17.0 이 references/bogo-munche.md 로 공개한 수치를 임계값 근거로
1179
+ * 삼았다(서술형 `~다` 종결 0/264 항목, 항목 중앙 31자, 결론 중앙 30자, 물음표·느낌표
1180
+ * 본문 0건). 규칙 코드·정규식·판정 로직은 kordoc 자체 구현이다.
1181
+ *
1182
+ * 범위: 검수는 조언용이다 — 생성은 막지 않고 경고만 낸다(표기법 검수·폰트 경고와 같은
1183
+ * 원칙). 문체 *변환*은 여전히 엔진 범위 밖이다(gongmunseo-engine-spec.md).
1184
+ * 상세 규칙과 예문은 docs/gaejosik-munche.md.
1185
+ */
1186
+ interface MuncheLintFinding {
1187
+ /** 1-based 줄 번호 */
1188
+ line: number;
1189
+ /** 걸린 원문 조각 */
1190
+ match: string;
1191
+ /** 규칙 코드 (DA_ENDING 등) */
1192
+ rule: string;
1193
+ severity: "error" | "warning";
1194
+ /** 판정된 줄 종류 — 같은 문장도 층에 따라 허용 여부가 다르다 */
1195
+ kind: MuncheLineKind;
1196
+ message: string;
1197
+ suggest?: string;
1198
+ }
1199
+ /**
1200
+ * 개조식 문체를 쓰는 프리셋 — 보고서·계획서·개조식보고서.
1201
+ * 기안문·시행문(official)은 경어 종결(`~하시기 바랍니다`), 통지·회의록·보도자료도
1202
+ * 각기 다른 문체 관행이라 이 검수를 적용하지 않는다. 적용 범위를 좁히는 것이
1203
+ * 오탐을 막는 가장 확실한 수단이다.
1204
+ */
1205
+ declare function usesGaejosikMunche(preset?: string): boolean;
1206
+ /** □ 소제목 / ❍ 항목 / - 세부 / ⇒ 결론 / > 리드문 / ※ 참고 / 그 밖 */
1207
+ type MuncheLineKind = "dae" | "item" | "sub" | "concl" | "lead" | "note" | "para";
1208
+ /**
1209
+ * 원고(마크다운/텍스트) 문체 검수. 코드펜스 안은 건너뛴다 — 예시 코드가 종결·대조
1210
+ * 규칙에 오탐되는 것 방지(표기법 검수와 같은 원칙).
1211
+ */
1212
+ declare function lintMuncheText(text: string): MuncheLintFinding[];
1213
+ /** 검수 결과를 사람이 읽는 경고 문자열 배열로 — generate 경고 채널(표기법과 동일)용 */
1214
+ declare function muncheLintWarnings(text: string, limit?: number): string[];
1215
+
1171
1216
  /**
1172
1217
  * 한글 조판 텍스트 폭 계산 — 함초롬바탕(HCR Batang) 실측 advance 테이블
1173
1218
  *
@@ -1863,4 +1908,4 @@ interface FillFormOutput {
1863
1908
  */
1864
1909
  declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillInput>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1865
1910
 
1866
- export { BUILTIN_TEMPLATES, type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type BuiltinTemplate, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type ChunkOptions, type ClickHereField, DEFAULT_REDACT_RULES, type DiffChangeType, type DiffResult, type DocChunk, type DocumentMetadata, type DocumentQualitySummary, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillInput, type FillOutputFormat, type FillResult, type FillValue, type FormField, type FormFieldSchema, type FormFieldType, type FormResult, type FormSchemaResult, type FormatProfile, type GongmunFont, type GongmunLintFinding, type GongmunNumbering, type GongmunOptions, type GongmunPreset, type GongmunPresetInput, type HwpxFillResult, HwpxSession, type HwpxTheme, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type MarkdownToHwpxOptions, type MeasureOptions, type OcrProvider, type OutlineItem, PRESET_ALIAS, type PageMargin, type PageMarkdown, type PageOptions, type PageQuality, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PatchOptions, type PatchResult, type PatchSkip, type PlaceSealResult, type PrintOptions, type PrintPreset, type RedactHit, type RedactOptions, type RedactRule, type RedactTextResult, type RenderSvgOptions, type RenderSvgResult, SPACE_EM_FIXED, SPACE_EM_FONT, type ScanCell, type ScanParaKind, type ScanParagraph, type ScanTable, type SealOp, type SealPlacement, type SectionScan, type SpliceEdit, type TRange, type TableProfile, VERSION, type ValidateIssue, type ValidateResult, ValueCursor, type WarningCode, type WatchOptions, type WrapMode, type WrapResult, applySplices, blocksToChunks, blocksToMarkdown, blocksToPages, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractClickHereFields, extractFormFields, extractFormSchema, fillForm, fillFormFields, fillHwpx, fillWithUniqueGuard, fitRatioForFewerLines, formatFillValue, gongmunLintWarnings, hwpxToProfile, incompatibleGongmunWarnings, inferFieldType, isHwpxFile, isKnownFont, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, lintGongmunText, markdownToHwpx, markdownToPdf, measureTextWidth, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parseImage, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, readBuiltinTemplate, readBuiltinTemplateSample, redactMarkdown, redactText, renderHtml, renderHwpxToSvg, resolveBuiltinTemplate, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, validateHwpx };
1911
+ export { BUILTIN_TEMPLATES, type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type BuiltinTemplate, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type ChunkOptions, type ClickHereField, DEFAULT_REDACT_RULES, type DiffChangeType, type DiffResult, type DocChunk, type DocumentMetadata, type DocumentQualitySummary, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillInput, type FillOutputFormat, type FillResult, type FillValue, type FormField, type FormFieldSchema, type FormFieldType, type FormResult, type FormSchemaResult, type FormatProfile, type GongmunFont, type GongmunLintFinding, type GongmunNumbering, type GongmunOptions, type GongmunPreset, type GongmunPresetInput, type HwpxFillResult, HwpxSession, type HwpxTheme, type IRBlock, type IRBlockType, type IRCell, type IRTable, type ImageData, type InlineStyle, type MarkdownToHwpxOptions, type MeasureOptions, type MuncheLineKind, type MuncheLintFinding, type OcrProvider, type OutlineItem, PRESET_ALIAS, type PageMargin, type PageMarkdown, type PageOptions, type PageQuality, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PatchOptions, type PatchResult, type PatchSkip, type PlaceSealResult, type PrintOptions, type PrintPreset, type RedactHit, type RedactOptions, type RedactRule, type RedactTextResult, type RenderSvgOptions, type RenderSvgResult, SPACE_EM_FIXED, SPACE_EM_FONT, type ScanCell, type ScanParaKind, type ScanParagraph, type ScanTable, type SealOp, type SealPlacement, type SectionScan, type SpliceEdit, type TRange, type TableProfile, VERSION, type ValidateIssue, type ValidateResult, ValueCursor, type WarningCode, type WatchOptions, type WrapMode, type WrapResult, applySplices, blocksToChunks, blocksToMarkdown, blocksToPages, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, extractClickHereFields, extractFormFields, extractFormSchema, fillForm, fillFormFields, fillHwpx, fillWithUniqueGuard, fitRatioForFewerLines, formatFillValue, gongmunLintWarnings, hwpxToProfile, incompatibleGongmunWarnings, inferFieldType, isHwpxFile, isKnownFont, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, lintGongmunText, lintMuncheText, markdownToHwpx, markdownToPdf, measureTextWidth, muncheLintWarnings, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parseImage, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, readBuiltinTemplate, readBuiltinTemplateSample, redactMarkdown, redactText, renderHtml, renderHwpxToSvg, resolveBuiltinTemplate, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, usesGaejosikMunche, validateHwpx };
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  flattenLayoutTables,
9
9
  inlineImagesIntoMarkdown,
10
10
  mapPuaText
11
- } from "./chunk-YZWSTDT7.js";
11
+ } from "./chunk-VYGNPB2X.js";
12
12
  import {
13
13
  parsePageRange
14
14
  } from "./chunk-GE43BE46.js";
@@ -29,7 +29,7 @@ import {
29
29
  sanitizeHref,
30
30
  stripDtd,
31
31
  toArrayBuffer
32
- } from "./chunk-IJH3NEF3.js";
32
+ } from "./chunk-OOT54JF2.js";
33
33
 
34
34
  // src/index.ts
35
35
  import { readFile } from "fs/promises";
@@ -570,9 +570,9 @@ function decryptEntry(cipher, entry, startKey) {
570
570
  const decipher = createDecipheriv("aes-256-cbc", key, entry.iv);
571
571
  decipher.setAutoPadding(false);
572
572
  const raw = Buffer.concat([decipher.update(cipher), decipher.final()]);
573
- const plain = inflateRawSync(raw, { maxOutputLength: MAX_DECOMPRESS_SIZE });
574
- const sum = createHash("sha256").update(plain.subarray(0, Math.min(CHECKSUM_PREFIX_BYTES, plain.length))).digest();
575
- if (sum.length === entry.checksum.length && timingSafeEqual(sum, entry.checksum)) return plain;
573
+ const plain2 = inflateRawSync(raw, { maxOutputLength: MAX_DECOMPRESS_SIZE });
574
+ const sum = createHash("sha256").update(plain2.subarray(0, Math.min(CHECKSUM_PREFIX_BYTES, plain2.length))).digest();
575
+ if (sum.length === entry.checksum.length && timingSafeEqual(sum, entry.checksum)) return plain2;
576
576
  } catch {
577
577
  }
578
578
  }
@@ -588,13 +588,13 @@ async function decryptHwpxInPlace(zip, manifestXml, password) {
588
588
  if (!file) {
589
589
  throw new KordocError(`\uC554\uD638 \uBAA9\uB85D\uC5D0 \uC788\uB294 \uD30C\uC77C\uC774 \uBB38\uC11C\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4: ${entry.path}`);
590
590
  }
591
- const plain = decryptEntry(await file.async("nodebuffer"), entry, startKey);
592
- if (!plain) {
591
+ const plain2 = decryptEntry(await file.async("nodebuffer"), entry, startKey);
592
+ if (!plain2) {
593
593
  throw new KordocError("\uBE44\uBC00\uBC88\uD638\uAC00 \uC77C\uCE58\uD558\uC9C0 \uC54A\uAC70\uB098 \uC554\uD638\uD654 \uB370\uC774\uD130\uAC00 \uC190\uC0C1\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
594
594
  }
595
- decrypted.push({ path: entry.path, plain });
595
+ decrypted.push({ path: entry.path, plain: plain2 });
596
596
  }
597
- for (const { path, plain } of decrypted) zip.file(path, plain);
597
+ for (const { path, plain: plain2 } of decrypted) zip.file(path, plain2);
598
598
  zip.file("META-INF/manifest.xml", stripEncryptionData(manifestXml));
599
599
  return decrypted.length;
600
600
  }
@@ -22530,7 +22530,7 @@ function gaejosikSizes(bodyHeight, ov = {}) {
22530
22530
  }
22531
22531
  function gaejosikSpaceBefore(depth, bodyHeight) {
22532
22532
  const s = bodyHeight / 1500;
22533
- const ui = [3e3, 2e3, 1200, 600][Math.min(depth, 3)];
22533
+ const ui = [300, 0, 0, 0][Math.min(depth, 3)];
22534
22534
  return Math.round(ui * s);
22535
22535
  }
22536
22536
  function gaejosikLevelIndent(depth, bodyHeight, sizes = {}, bullet2 = "\u25CB") {
@@ -22953,7 +22953,9 @@ var GJ_CHAR_BAR = 24;
22953
22953
  var GJ_CHAR_BODY_TITLE = 25;
22954
22954
  var GJ_CHAR_TITLE_BAR = 26;
22955
22955
  var GJ_CHAR_APPROVAL = 27;
22956
- var GJ_CHAR_COUNT = GJ_CHAR_APPROVAL - GJ_CHAR_DAE + 1;
22956
+ var GJ_CHAR_SRC = 28;
22957
+ var GJ_CHAR_SRC_BOLD = 29;
22958
+ var GJ_CHAR_COUNT = GJ_CHAR_SRC_BOLD - GJ_CHAR_DAE + 1;
22957
22959
  var GJ_PARA_CHAM = 20;
22958
22960
  var GJ_PARA_COVER = 21;
22959
22961
  var GJ_PARA_TOC_ITEM = 22;
@@ -22961,7 +22963,8 @@ var GJ_PARA_CHAPTER = 23;
22961
22963
  var GJ_PARA_BAR = 24;
22962
22964
  var GONGMUN_LIST_PLAIN_BASE = 25;
22963
22965
  var GONGMUN_PARA_APPROVAL = GONGMUN_LIST_PLAIN_BASE + GONGMUN_LIST_LEVELS;
22964
- var GONGMUN_LIST_VARIANT_BASE = GONGMUN_PARA_APPROVAL + 1;
22966
+ var GONGMUN_SRC_LEFT = GONGMUN_PARA_APPROVAL + 1;
22967
+ var GONGMUN_LIST_VARIANT_BASE = GONGMUN_SRC_LEFT + 1;
22965
22968
  var GJ_BF_CHAPTER_NUM = 3;
22966
22969
  var GJ_BF_CHAPTER_GAP = 4;
22967
22970
  var GJ_BF_CHAPTER_TITLE = 5;
@@ -23005,10 +23008,15 @@ var GONGMUN_TBL_CHAR_BOLD = 12;
23005
23008
  var GONGMUN_TBL_PT = 1200;
23006
23009
  var GONGMUN_TITLE_BAR_CHAR = 13;
23007
23010
  var GONGMUN_APPROVAL_CHAR = 14;
23011
+ var GONGMUN_SRC_CHAR = 15;
23012
+ var GONGMUN_SRC_CHAR_BOLD = 16;
23013
+ function srcCaptionPt(bodyHeight) {
23014
+ return Math.max(bodyHeight - 300, 1e3);
23015
+ }
23008
23016
  var CHAR_VARIANT_BASE = CHAR_QUOTE + 1;
23009
23017
  function charVariantBase(richAssets, isGongmun = true) {
23010
23018
  if (!isGongmun) return CHAR_VARIANT_BASE;
23011
- return richAssets ? CHAR_VARIANT_BASE + GJ_CHAR_COUNT : CHAR_VARIANT_BASE + (GONGMUN_APPROVAL_CHAR - GONGMUN_TBL_CHAR + 1);
23019
+ return richAssets ? CHAR_VARIANT_BASE + GJ_CHAR_COUNT : CHAR_VARIANT_BASE + (GONGMUN_SRC_CHAR_BOLD - GONGMUN_TBL_CHAR + 1);
23012
23020
  }
23013
23021
  var GONGMUN_BODY_RATIO = 95;
23014
23022
 
@@ -23047,6 +23055,7 @@ function buildPrvText(blocks) {
23047
23055
  }
23048
23056
  return lines.join("\n").slice(0, 1024);
23049
23057
  }
23058
+ var BUNIM_HEAD = /^붙\s*임(?:\s|:|$)/;
23050
23059
  function findMathDelim(s, from) {
23051
23060
  let i = s.indexOf("$$", from);
23052
23061
  while (i > 0) {
@@ -23062,9 +23071,11 @@ function parseMarkdownToBlocks(md2) {
23062
23071
  const blocks = [];
23063
23072
  let i = 0;
23064
23073
  const listStack = [];
23074
+ let inBunim = false;
23065
23075
  while (i < lines.length) {
23066
23076
  const line = lines[i];
23067
23077
  if (!line.trim()) {
23078
+ inBunim = false;
23068
23079
  i++;
23069
23080
  continue;
23070
23081
  }
@@ -23192,6 +23203,19 @@ function parseMarkdownToBlocks(md2) {
23192
23203
  if (joined.length) blocks.push({ type: "blockquote", text: joined.join("\n") });
23193
23204
  continue;
23194
23205
  }
23206
+ if (BUNIM_HEAD.test(line.trim())) inBunim = true;
23207
+ if (inBunim) {
23208
+ if (BUNIM_HEAD.test(line.trim())) {
23209
+ const prevBlock = blocks[blocks.length - 1];
23210
+ if (blocks.length && !(prevBlock.type === "paragraph" && !prevBlock.text)) {
23211
+ blocks.push({ type: "paragraph", text: "" });
23212
+ }
23213
+ }
23214
+ blocks.push({ type: "paragraph", text: line.replace(/\s+$/, "") });
23215
+ listStack.length = 0;
23216
+ i++;
23217
+ continue;
23218
+ }
23195
23219
  const listLine = line.replace(/^[\t ]+/, (ws) => ws.replace(/\t/g, " "));
23196
23220
  const listMatch = listLine.match(/^(\s*)([-*+]|\d+[.)]) (.+)$/);
23197
23221
  if (listMatch) {
@@ -23494,7 +23518,10 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
23494
23518
  charPr(11, GONGMUN_TBL_PT, false, false, bodyFont, theme.body),
23495
23519
  charPr(12, GONGMUN_TBL_PT, true, false, bodyFont, theme.body),
23496
23520
  charPr(GONGMUN_TITLE_BAR_CHAR, 100, false, false, bodyFont, theme.body),
23497
- charPr(GONGMUN_APPROVAL_CHAR, 1e3, false, false, bodyFont, theme.body)
23521
+ charPr(GONGMUN_APPROVAL_CHAR, 1e3, false, false, bodyFont, theme.body),
23522
+ // 출처행 캡션 — 본문 폰트 -3pt (실무 보고서: 표 아래 출처는 본문과 구분되는 작은 글씨)
23523
+ charPr(GONGMUN_SRC_CHAR, srcCaptionPt(body), false, false, bodyFont, theme.body),
23524
+ charPr(GONGMUN_SRC_CHAR_BOLD, srcCaptionPt(body), true, false, bodyFont, theme.body)
23498
23525
  );
23499
23526
  }
23500
23527
  if (richAssets) {
@@ -23532,8 +23559,12 @@ function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls
23532
23559
  // 본문 제목박스(HY헤드라인M 22pt, 실측 GT3 표④)
23533
23560
  charPr(GJ_CHAR_TITLE_BAR, 100, false, false, 4),
23534
23561
  // 1페이지형 제목박스 바(1pt)
23535
- charPr(GJ_CHAR_APPROVAL, 1e3, false, false, 7)
23562
+ charPr(GJ_CHAR_APPROVAL, 1e3, false, false, 7),
23536
23563
  // 결재란 라벨(맑은 고딕 10pt)
23564
+ charPr(GJ_CHAR_SRC, srcCaptionPt(body), false, false, 5),
23565
+ // 출처행 캡션(한양중고딕 본문-3pt)
23566
+ charPr(GJ_CHAR_SRC_BOLD, srcCaptionPt(body), true, false, 5)
23567
+ // 출처행 캡션 bold
23537
23568
  );
23538
23569
  }
23539
23570
  const expectedBase = charVariantBase(richAssets, !!gongmun);
@@ -23575,13 +23606,18 @@ ${base2.join("\n")}
23575
23606
  }
23576
23607
  const ls = gongmun.lineSpacing;
23577
23608
  const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
23578
- const h2Geom = gongmun.h2Marker !== "none" ? { spaceBefore: Math.round(gongmun.bodyHeight * 2), spaceAfter: 0, indent: -markerWidth(gongmun.h2Marker === "box" ? "\u25A1" : "1.", 1600) } : { spaceBefore: 600, spaceAfter: 150 };
23609
+ const h2MarkerWidth = markerWidth(gongmun.h2Marker === "box" ? "\u25A1" : "1.", 1600);
23610
+ const h2Geom = gongmun.h2Marker !== "none" ? { spaceBefore: Math.round(gongmun.bodyHeight * 2), spaceAfter: 0, indent: -h2MarkerWidth } : { spaceBefore: 600, spaceAfter: 150 };
23611
+ const h3Left = gongmun.h2Marker !== "none" ? h2MarkerWidth : 0;
23579
23612
  const base = [
23580
23613
  paraPr(0, { lineSpacing: ls, keepWord: true }),
23581
23614
  paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true }),
23582
23615
  paraPr(2, { align: "LEFT", ...h2Geom, lineSpacing: ls, keepWord: true }),
23583
- paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
23584
- paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
23616
+ // h3·h4 소제목("가." "1)")은 h2(□) 대항목의 하위다 — 종전에는 left가 없어 h2 부호가
23617
+ // 내어쓰기로 왼쪽에 나간 뒤 소제목이 본문 경계에서 시작해, 실렌더상 소제목이 대항목보다
23618
+ // 왼쪽에 놓이며 계층이 사라졌다(실렌더 확인). h2 부호폭만큼 들여써 h2 제목 글자와 맞춘다.
23619
+ paraPr(3, { align: "LEFT", left: h3Left, spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
23620
+ paraPr(4, { align: "LEFT", left: h3Left + Math.round(gongmun.bodyHeight / 2), spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
23585
23621
  paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
23586
23622
  paraPr(6, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true }),
23587
23623
  paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
@@ -23616,6 +23652,7 @@ ${base2.join("\n")}
23616
23652
  base.push(paraPr(GONGMUN_LIST_PLAIN_BASE + d, { align: listAlign, lineSpacing: ls, left, indent: 0, spaceBefore: sectionGap, keepWord: true }));
23617
23653
  }
23618
23654
  base.push(paraPr(GONGMUN_PARA_APPROVAL, { align: "CENTER", lineSpacing: 100, keepWord: true }));
23655
+ base.push(paraPr(GONGMUN_SRC_LEFT, { align: "LEFT", lineSpacing: ls, keepWord: true }));
23619
23656
  for (let vi = 0; vi < listIndentVariants.length; vi++) {
23620
23657
  const { depth, widthHu } = listIndentVariants[vi];
23621
23658
  const { left } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering, gongmun.sizes, gongmun.bullet2, usesAsteriskThird(gongmun.preset));
@@ -26191,7 +26228,17 @@ function renderParagraph(block, blockIdx, ctx) {
26191
26228
  const ctr = gongmun && /^<center>([\s\S]*)<\/center>$/i.exec((block.text || "").trim());
26192
26229
  const rgt = gongmun && /^<right>([\s\S]*)<\/right>$/i.exec((block.text || "").trim());
26193
26230
  if (ctr) return generateParagraph(ctr[1].trim(), GONGMUN_CENTER);
26194
- if (rgt) return generateParagraph(rgt[1].trim(), GONGMUN_RIGHT);
26231
+ if (rgt) {
26232
+ const t = rgt[1].trim();
26233
+ const isSrc = /^(출처|자료)\s*[::]/.test(t);
26234
+ const srcChar = ctx.richAssets ? GJ_CHAR_SRC : GONGMUN_SRC_CHAR;
26235
+ const srcBold = ctx.richAssets ? GJ_CHAR_SRC_BOLD : GONGMUN_SRC_CHAR_BOLD;
26236
+ const h = isSrc ? srcCaptionPt(gongmun.bodyHeight) : gongmun.bodyHeight;
26237
+ const fits = measureTextWidth(t, h, isSrc ? 100 : GONGMUN_BODY_RATIO) <= ctx.gjBodyW + 0.5;
26238
+ const paraId = fits ? GONGMUN_RIGHT : GONGMUN_SRC_LEFT;
26239
+ if (!isSrc) return generateParagraph(t, paraId);
26240
+ return generateParagraph(t, paraId, srcChar, (id) => id === CHAR_BOLD ? srcBold : id);
26241
+ }
26195
26242
  return generateParagraph(block.text || "", PARA_NORMAL, CHAR_NORMAL, fit ? variantMapper(fit, blockIdx, vBase) : void 0);
26196
26243
  }
26197
26244
  function renderCodeBlock(block, blockIdx, ctx) {
@@ -26288,8 +26335,8 @@ function renderHtmlTable(block, ctx) {
26288
26335
  ctx.opener.emitCarrier(ctx.paraXmls);
26289
26336
  return `<hp:p paraPrIDRef="${tableStyle && bfReg ? GONGMUN_RIGHT : 0}" styleIDRef="0"><hp:run charPrIDRef="0">${tbl2}</hp:run></hp:p>`;
26290
26337
  }
26291
- const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
26292
- return plain ? generateParagraph(plain) : "";
26338
+ const plain2 = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
26339
+ return plain2 ? generateParagraph(plain2) : "";
26293
26340
  }
26294
26341
  function appendPostamble(blocks, ctx) {
26295
26342
  const { gongmun, dfIds, bfReg, tableStyle, paraXmls } = ctx;
@@ -27703,6 +27750,233 @@ function gongmunLintWarnings(text, limit = 10) {
27703
27750
  return shown;
27704
27751
  }
27705
27752
 
27753
+ // src/hwpx/munche-lint.ts
27754
+ function usesGaejosikMunche(preset) {
27755
+ const p = normalizeGongmunPreset(preset);
27756
+ return p === "gaejosik" || p === "report" || p === "plan";
27757
+ }
27758
+ var ITEM_MAX = 70;
27759
+ var CONCL_MAX = 60;
27760
+ var LEAD_MAX = 140;
27761
+ function classify(raw) {
27762
+ const indent = raw.length - raw.trimStart().length;
27763
+ const t = raw.trim();
27764
+ if (!t) return null;
27765
+ if (t.startsWith("#") || t.startsWith("|") || t.startsWith("![") || /^[-=*_]{3,}$/.test(t)) return null;
27766
+ if (t.startsWith(">")) return { kind: "lead", body: t.slice(1).trim() };
27767
+ if (/^(?:⇒|=>|➡|→)/.test(t)) return { kind: "concl", body: t.replace(/^(?:⇒|=>|➡|→)\s*/, "") };
27768
+ if (/^(?:※|\*\s)/.test(t)) return { kind: "note", body: t.replace(/^(?:※|\*)\s*/, "") };
27769
+ if (t.startsWith("\u25A1")) return { kind: "dae", body: t.slice(1).trim() };
27770
+ if (/^(?:○|❍|ㅇ|◦)/.test(t)) return { kind: "item", body: t.slice(1).trim() };
27771
+ const li = /^(?:[-•ㆍ·]|\d+[.)])\s+(.*)$/.exec(t);
27772
+ if (li) return { kind: indent >= 2 ? "sub" : "item", body: li[1].trim() };
27773
+ return { kind: "para", body: t };
27774
+ }
27775
+ function plain(s) {
27776
+ return s.replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/(\*\*|__|~~|`)/g, "").trim();
27777
+ }
27778
+ function stripQuoted(s) {
27779
+ return s.replace(/[“"'‘][^”"'’]{0,80}[”"'’]/g, "").replace(/\([^)]{0,80}\)/g, "");
27780
+ }
27781
+ var DA_ENDING = /[가-힣]다\.?$/;
27782
+ var DEONTIC = /(?:해야|하여야|되어야|돼야|필요가 있)\s*(?:한다|함|합니다|하겠음)\.?$|할 것\.?$/;
27783
+ var GEOSIDA = /것(?:이다|임)\.?$/;
27784
+ var LEAD_ENDING = /(?:하고자|하려|고자)\s*함\.?$/;
27785
+ var NOT_A_BUT = /(?:아니라|아닌|아니고|아니며)\s*,?\s*([가-힣]{1,12})/g;
27786
+ var ABSTRACT = [
27787
+ "\uC0AC\uB78C",
27788
+ "\uB9C8\uC74C",
27789
+ "\uBCF8\uC9C8",
27790
+ "\uC804\uD658",
27791
+ "\uD0DC\uB3C4",
27792
+ "\uBB38\uD654",
27793
+ "\uCCA0\uD559",
27794
+ "\uAC00\uCE58",
27795
+ "\uC815\uC2E0",
27796
+ "\uAD00\uACC4",
27797
+ "\uC2E0\uB8B0",
27798
+ "\uACFC\uC815",
27799
+ "\uC9C8\uBB38",
27800
+ "\uC774\uC57C\uAE30",
27801
+ "\uACBD\uD5D8",
27802
+ "\uC2DC\uAC04",
27803
+ "\uACF5\uAC04",
27804
+ "\uC5F0\uACB0",
27805
+ "\uBCC0\uD654",
27806
+ "\uBBF8\uB798",
27807
+ "\uC2DC\uC791",
27808
+ "\uC6A9\uAE30",
27809
+ "\uC758\uC9C0",
27810
+ "\uBC29\uBC95",
27811
+ "\uC790\uC138",
27812
+ "\uC758\uC2DD",
27813
+ "\uC5ED\uB7C9"
27814
+ ];
27815
+ var COUPLET = /[은는이가]\s*[^,]{2,15},\s*[^,]{2,15}[은는이가]\s*[^,]{2,15}$/;
27816
+ var DATE_KOREAN = /\d{4}년\s*\d{1,2}월/;
27817
+ function lintMuncheText(text) {
27818
+ const findings = [];
27819
+ const lines = text.split(/\r?\n/);
27820
+ let fenceMarker = null;
27821
+ let frontMatter = false;
27822
+ let leadBuf = [];
27823
+ const add = (line, kind, severity, rule, match, message, suggest) => {
27824
+ findings.push({ line, kind, severity, rule, match: match.slice(0, 60), message, suggest });
27825
+ };
27826
+ const flushLead = () => {
27827
+ if (!leadBuf.length) return;
27828
+ const block = leadBuf.map((l) => l.body).join(" ").trim();
27829
+ const at = leadBuf[0].line;
27830
+ leadBuf = [];
27831
+ if (block.length < 20) return;
27832
+ if (!LEAD_ENDING.test(block)) {
27833
+ add(
27834
+ at,
27835
+ "lead",
27836
+ "warning",
27837
+ "LEAD_ENDING",
27838
+ block,
27839
+ "\uB9AC\uB4DC\uBB38\uC740 '~\uD558\uACE0\uC790 \uD568.' \uD55C \uBB38\uC7A5",
27840
+ "[\uC218\uB2E8]\uD558\uACE0, [\uC218\uB2E8]\uD558\uC5EC [\uBAA9\uC801]\uD558\uACE0\uC790 \uD568."
27841
+ );
27842
+ }
27843
+ const sentences = (block.match(/\./g) ?? []).length;
27844
+ if (block.length > LEAD_MAX || sentences > 1) {
27845
+ add(
27846
+ at,
27847
+ "lead",
27848
+ "warning",
27849
+ "LEAD_LONG",
27850
+ block,
27851
+ `\uB9AC\uB4DC\uBB38 ${block.length}\uC790\xB7\uBB38\uC7A5 ${sentences}\uAC1C \u2014 \uC2E4\uCE21\uC740 \uD55C \uBB38\uC7A5 40~120\uC790`,
27852
+ "\uC218\uB2E8 \uB458\xB7\uBAA9\uC801 \uD558\uB098\uB85C \uC555\uCD95"
27853
+ );
27854
+ }
27855
+ };
27856
+ for (let i = 0; i < lines.length; i++) {
27857
+ const raw = lines[i];
27858
+ const no = i + 1;
27859
+ if (raw.trim() === "---" && (frontMatter || no <= 3)) {
27860
+ if (no <= 3 || frontMatter) frontMatter = !frontMatter;
27861
+ continue;
27862
+ }
27863
+ if (frontMatter) continue;
27864
+ const fence = raw.match(/^\s*(```+|~~~+)/);
27865
+ if (fence) {
27866
+ const kind = fence[1][0];
27867
+ if (fenceMarker === null) fenceMarker = kind;
27868
+ else if (kind === fenceMarker) fenceMarker = null;
27869
+ continue;
27870
+ }
27871
+ if (fenceMarker !== null) continue;
27872
+ const c = classify(raw);
27873
+ if (!c) {
27874
+ flushLead();
27875
+ continue;
27876
+ }
27877
+ if (c.kind === "lead") {
27878
+ leadBuf.push({ line: no, body: plain(c.body) });
27879
+ continue;
27880
+ }
27881
+ flushLead();
27882
+ const b = plain(c.body);
27883
+ if (!b) continue;
27884
+ const q = stripQuoted(b);
27885
+ if (c.kind === "item" || c.kind === "sub" || c.kind === "concl" || c.kind === "para") {
27886
+ if (DA_ENDING.test(q)) {
27887
+ add(
27888
+ no,
27889
+ c.kind,
27890
+ "error",
27891
+ "DA_ENDING",
27892
+ b,
27893
+ "'~\uB2E4' \uC11C\uC220\uD615 \uC885\uACB0 \u2014 \uC2E4\uCE21 0%(\uD56D\uBAA9 0/264)",
27894
+ "\uBA85\uC0AC\xB7\uBA85\uC0AC\uAD6C \uB610\uB294 '~\uD568/\uC788\uC74C'\uC73C\uB85C"
27895
+ );
27896
+ }
27897
+ if (GEOSIDA.test(q)) {
27898
+ add(no, c.kind, "warning", "GEOSIDA", b, "'~\uAC83\uC774\uB2E4/\uAC83\uC784' \u2014 \uC2E4\uCE21 1\uAC74\uBFD0", "\uBA85\uC0AC \uC885\uACB0\uB85C");
27899
+ }
27900
+ }
27901
+ if (DEONTIC.test(q)) {
27902
+ add(
27903
+ no,
27904
+ c.kind,
27905
+ "error",
27906
+ "DEONTIC",
27907
+ b,
27908
+ "'~\uD574\uC57C \uD55C\uB2E4' \uB2F9\uC704 \uC885\uACB0 \u2014 \uD310\uB2E8\uC740 \uBA85\uC0AC\uB85C \uB05D\uB9FA\uC74C",
27909
+ "\uC608) \u21D2 \uC9C0\uC5ED\uB9DE\uCDA4\uD615 \uBCF4\uAE09 \uD544\uC694"
27910
+ );
27911
+ }
27912
+ NOT_A_BUT.lastIndex = 0;
27913
+ for (const m of q.matchAll(NOT_A_BUT)) {
27914
+ const tail = m[1] ?? "";
27915
+ if (ABSTRACT.some((w) => tail.includes(w))) {
27916
+ add(
27917
+ no,
27918
+ c.kind,
27919
+ "error",
27920
+ "RHETORIC_CONTRAST",
27921
+ m[0].trim(),
27922
+ `'\uC544\uB2C8\uB77C ${tail}' \u2014 B\uAC00 \uCD94\uC0C1\uC5B4\xB7\uAC00\uCE58\uC5B4\uBA74 \uC218\uC0AC(\uC2E4\uCE21 0\uAC74)`,
27923
+ "\uB450 \uAD6C\uCCB4 \uC120\uD0DD\uC9C0\uB97C \uAC00\uB974\uB294 \uACBD\uC6B0\uB9CC \uD5C8\uC6A9"
27924
+ );
27925
+ } else {
27926
+ add(
27927
+ no,
27928
+ c.kind,
27929
+ "warning",
27930
+ "CONTRAST_CHECK",
27931
+ m[0].trim(),
27932
+ `'\uC544\uB2C8\uB77C ${tail}' \u2014 B\uAC00 \uAD6C\uCCB4 \uC120\uD0DD\uC9C0(\uC81C\uB3C4\xB7\uC7A5\uC18C\xB7\uC808\uCC28)\uC778\uC9C0 \uD655\uC778`
27933
+ );
27934
+ }
27935
+ }
27936
+ if (c.kind !== "note" && /[?!?!]/.test(q)) {
27937
+ add(no, c.kind, "error", "QUESTION_EXCLAIM", b, "\uBB3C\uC74C\uD45C\xB7\uB290\uB08C\uD45C \u2014 \uBCF8\uBB38 \uC2E4\uCE21 0\uAC74");
27938
+ }
27939
+ if ((c.kind === "item" || c.kind === "para" || c.kind === "dae") && COUPLET.test(q)) {
27940
+ add(no, c.kind, "warning", "COUPLET", b, "\uB300\uAD6C(\u5C0D\u53E5)\uB85C \uBCF4\uC784 \u2014 \uC2AC\uB85C\uAC74 \uBB38\uC7A5\uC740 \uC2E4\uCE21 0\uAC74", "\uBAA9\uD45C \uC218\uCE58\xB7\uBA85\uC0AC\uB85C");
27941
+ }
27942
+ if (c.kind === "item" && b.length > ITEM_MAX) {
27943
+ add(
27944
+ no,
27945
+ c.kind,
27946
+ "warning",
27947
+ "ITEM_LONG",
27948
+ b,
27949
+ `\uD56D\uBAA9 ${b.length}\uC790 \u2014 \uC2E4\uCE21 \uC911\uC559 31\uC790, 2\uC904 \uD55C\uACC4`,
27950
+ "\uADFC\uAC70\xB7\uC608\uC2DC\uB294 \uC138\uBD80(-)\uB85C \uB0B4\uB9BC"
27951
+ );
27952
+ }
27953
+ if (c.kind === "concl" && b.length > CONCL_MAX) {
27954
+ add(
27955
+ no,
27956
+ c.kind,
27957
+ "warning",
27958
+ "CONCL_LONG",
27959
+ b,
27960
+ `\uACB0\uB860 ${b.length}\uC790 \u2014 \uC2E4\uCE21 \uC911\uC559 30\uC790`,
27961
+ "\uD310\uB2E8 \uD558\uB098\uB9CC \uB0A8\uAE40"
27962
+ );
27963
+ }
27964
+ if (DATE_KOREAN.test(b)) {
27965
+ add(no, c.kind, "warning", "DATE_KOREAN", b, "\uC5F0\xB7\uC6D4\uC744 \uAE00\uC790\uB85C \uD45C\uAE30", "\uC608) 2026. 8. 22.");
27966
+ }
27967
+ }
27968
+ flushLead();
27969
+ return findings;
27970
+ }
27971
+ function muncheLintWarnings(text, limit = 10) {
27972
+ const findings = lintMuncheText(text);
27973
+ const shown = findings.slice(0, limit).map(
27974
+ (f) => `\uBB38\uCCB4 [${f.rule}] L${f.line} "${f.match}" \u2014 ${f.message}${f.suggest ? ` (${f.suggest})` : ""}`
27975
+ );
27976
+ if (findings.length > limit) shown.push(`\uBB38\uCCB4 \uACBD\uACE0 ${findings.length - limit}\uAC74 \uB354 \uC788\uC74C \u2014 kordoc lint --munche\uB85C \uC804\uCCB4 \uD655\uC778`);
27977
+ return shown;
27978
+ }
27979
+
27706
27980
  // src/roundtrip/patcher.ts
27707
27981
  import JSZip11 from "jszip";
27708
27982
 
@@ -31685,7 +31959,7 @@ async function dispatch(format, buffer, opts) {
31685
31959
  }
31686
31960
  async function parseImage(buffer, options) {
31687
31961
  try {
31688
- const { parseImageDocument } = await import("./image-ocr-4CF6B2ZP.js");
31962
+ const { parseImageDocument } = await import("./image-ocr-YZ56O63S.js");
31689
31963
  const { blocks, warnings } = await parseImageDocument(buffer, options);
31690
31964
  return {
31691
31965
  success: true,
@@ -31744,7 +32018,7 @@ async function parseHwp(buffer, options) {
31744
32018
  async function parsePdf(buffer, options) {
31745
32019
  let parsePdfDocument;
31746
32020
  try {
31747
- const mod = await import("./parser-O3X37357.js");
32021
+ const mod = await import("./parser-6UL2HLDH.js");
31748
32022
  parsePdfDocument = mod.parsePdfDocument;
31749
32023
  } catch {
31750
32024
  return {
@@ -31875,9 +32149,11 @@ export {
31875
32149
  isPdfFile,
31876
32150
  isZipFile,
31877
32151
  lintGongmunText,
32152
+ lintMuncheText,
31878
32153
  markdownToHwpx,
31879
32154
  markdownToPdf,
31880
32155
  measureTextWidth,
32156
+ muncheLintWarnings,
31881
32157
  normalizeGongmunPreset,
31882
32158
  openHwpxDocument,
31883
32159
  parse,
@@ -31905,6 +32181,7 @@ export {
31905
32181
  simulateWrap,
31906
32182
  simulateWrapKeepWord,
31907
32183
  unknownFontWarnings,
32184
+ usesGaejosikMunche,
31908
32185
  validateHwpx
31909
32186
  };
31910
32187
  //# sourceMappingURL=index.js.map