kordoc 4.0.7 → 4.1.0

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 (123) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +837 -806
  3. package/dist/{-6HWEFXVV.js → -AS4IABL2.js} +24 -11
  4. package/dist/{chunk-BKWHX3RC.js → chunk-37HJHCPA.js} +24 -15
  5. package/dist/chunk-37HJHCPA.js.map +1 -0
  6. package/dist/{chunk-U25XGCNH.cjs → chunk-37VKMUST.cjs} +174 -25
  7. package/dist/chunk-37VKMUST.cjs.map +1 -0
  8. package/dist/{chunk-5OKHAJ62.js → chunk-4KI23VHA.js} +162 -13
  9. package/dist/chunk-4KI23VHA.js.map +1 -0
  10. package/dist/{chunk-6GBLFQMA.js → chunk-5RPYBC2Q.js} +1 -1
  11. package/dist/chunk-5RPYBC2Q.js.map +1 -0
  12. package/dist/{chunk-NGSHDBQR.js → chunk-AX2R5Q2N.js} +7 -4
  13. package/dist/chunk-AX2R5Q2N.js.map +1 -0
  14. package/dist/{chunk-X34YWRL5.cjs → chunk-DCZVOIEO.cjs} +1 -1
  15. package/dist/chunk-DCZVOIEO.cjs.map +1 -0
  16. package/dist/chunk-DZIXKL7E.js +145 -0
  17. package/dist/chunk-DZIXKL7E.js.map +1 -0
  18. package/dist/chunk-F2ZU3IZG.js +82 -0
  19. package/dist/chunk-F2ZU3IZG.js.map +1 -0
  20. package/dist/{chunk-AIQ3ISQU.js → chunk-GE43BE46.js} +1 -1
  21. package/dist/chunk-GE43BE46.js.map +1 -0
  22. package/dist/{chunk-Q7EN4EUJ.js → chunk-GQVSHGG4.js} +12 -4
  23. package/dist/chunk-GQVSHGG4.js.map +1 -0
  24. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  25. package/dist/{chunk-TJJTLM76.js → chunk-L2XQQTOY.js} +1422 -1121
  26. package/dist/chunk-L2XQQTOY.js.map +1 -0
  27. package/dist/{chunk-3TBUDJDE.js → chunk-MOL7MDBG.js} +1 -1
  28. package/dist/chunk-MOL7MDBG.js.map +1 -0
  29. package/dist/{chunk-CNM75ZSX.js → chunk-O5VS7RIR.js} +2 -2
  30. package/dist/chunk-O5VS7RIR.js.map +1 -0
  31. package/dist/{chunk-2SN3CKME.js → chunk-SSTK6IKK.js} +18 -21
  32. package/dist/chunk-SSTK6IKK.js.map +1 -0
  33. package/dist/chunk-UOO7LSDG.js +152 -0
  34. package/dist/chunk-UOO7LSDG.js.map +1 -0
  35. package/dist/{chunk-ONXVBURQ.js → chunk-WO52HVQJ.js} +2 -2
  36. package/dist/chunk-WO52HVQJ.js.map +1 -0
  37. package/dist/{chunk-CFQLK3LM.js → chunk-YOO6ET6M.js} +7 -3
  38. package/dist/chunk-YOO6ET6M.js.map +1 -0
  39. package/dist/chunks-WVMGF7JL.js +10 -0
  40. package/dist/cli.js +173 -38
  41. package/dist/cli.js.map +1 -1
  42. package/dist/{detect-NTR2FUEG.js → detect-YEZX2XCF.js} +2 -2
  43. package/dist/{formula-ZYUDQHD3.cjs → formula-5NKVS2LR.cjs} +1 -1
  44. package/dist/formula-5NKVS2LR.cjs.map +1 -0
  45. package/dist/{formula-KOQV353G.js → formula-JCNF43NE.js} +1 -1
  46. package/dist/formula-JCNF43NE.js.map +1 -0
  47. package/dist/{formula-MEDGYQXS.js → formula-RXVSQPXI.js} +1 -1
  48. package/dist/formula-RXVSQPXI.js.map +1 -0
  49. package/dist/index.cjs +1932 -1397
  50. package/dist/index.cjs.map +1 -1
  51. package/dist/index.d.cts +106 -2
  52. package/dist/index.d.ts +106 -2
  53. package/dist/index.js +1626 -1091
  54. package/dist/index.js.map +1 -1
  55. package/dist/mcp.js +275 -67
  56. package/dist/mcp.js.map +1 -1
  57. package/dist/page-range-737B4EZW.js +8 -0
  58. package/dist/page-range-LNMXJU6W.js +7 -0
  59. package/dist/page-range-P7SDW6LR.cjs +8 -0
  60. package/dist/page-range-P7SDW6LR.cjs.map +1 -0
  61. package/dist/{parser-E6U5TNAU.cjs → parser-N4A7UGDK.cjs} +314 -56
  62. package/dist/parser-N4A7UGDK.cjs.map +1 -0
  63. package/dist/{parser-5EHWYJMC.js → parser-PEOYBXBO.js} +287 -27
  64. package/dist/parser-PEOYBXBO.js.map +1 -0
  65. package/dist/{parser-UGB3NIVH.js → parser-XX4QTDFQ.js} +283 -25
  66. package/dist/parser-XX4QTDFQ.js.map +1 -0
  67. package/dist/{profile-io-CAKRPQRD.js → profile-io-PLDQFPJA.js} +3 -3
  68. package/dist/{provider-5K7O3Z2O.cjs → provider-4FAYHJ6N.cjs} +3 -3
  69. package/dist/provider-4FAYHJ6N.cjs.map +1 -0
  70. package/dist/{provider-H4WWSPOV.js → provider-C6IOGIS5.js} +3 -3
  71. package/dist/provider-C6IOGIS5.js.map +1 -0
  72. package/dist/{provider-7H4CPZYS.js → provider-UIBW2MIH.js} +3 -3
  73. package/dist/provider-UIBW2MIH.js.map +1 -0
  74. package/dist/rasterize-WWNQLKYW.js +40 -0
  75. package/dist/rasterize-WWNQLKYW.js.map +1 -0
  76. package/dist/redact-7ILEAUTS.js +12 -0
  77. package/dist/render-T7S6H6AN.js +10 -0
  78. package/dist/render-T7S6H6AN.js.map +1 -0
  79. package/dist/seal-7PTL6MXH.js +10 -0
  80. package/dist/seal-7PTL6MXH.js.map +1 -0
  81. package/dist/{setup-QSJ2INNS.js → setup-Q2PRE7UA.js} +5 -3
  82. package/dist/setup-Q2PRE7UA.js.map +1 -0
  83. package/dist/{watch-RMX427YR.js → watch-SFHXZALC.js} +78 -24
  84. package/dist/watch-SFHXZALC.js.map +1 -0
  85. package/package.json +97 -97
  86. package/dist/chunk-2SN3CKME.js.map +0 -1
  87. package/dist/chunk-3TBUDJDE.js.map +0 -1
  88. package/dist/chunk-5OKHAJ62.js.map +0 -1
  89. package/dist/chunk-6GBLFQMA.js.map +0 -1
  90. package/dist/chunk-AIQ3ISQU.js.map +0 -1
  91. package/dist/chunk-BKWHX3RC.js.map +0 -1
  92. package/dist/chunk-CFQLK3LM.js.map +0 -1
  93. package/dist/chunk-CNM75ZSX.js.map +0 -1
  94. package/dist/chunk-NGSHDBQR.js.map +0 -1
  95. package/dist/chunk-ONXVBURQ.js.map +0 -1
  96. package/dist/chunk-Q7EN4EUJ.js.map +0 -1
  97. package/dist/chunk-TJJTLM76.js.map +0 -1
  98. package/dist/chunk-U25XGCNH.cjs.map +0 -1
  99. package/dist/chunk-X34YWRL5.cjs.map +0 -1
  100. package/dist/formula-KOQV353G.js.map +0 -1
  101. package/dist/formula-MEDGYQXS.js.map +0 -1
  102. package/dist/formula-ZYUDQHD3.cjs.map +0 -1
  103. package/dist/page-range-CIRRJPXJ.js +0 -7
  104. package/dist/page-range-OF5I4PQY.js +0 -8
  105. package/dist/page-range-TPIRSA3J.cjs +0 -8
  106. package/dist/page-range-TPIRSA3J.cjs.map +0 -1
  107. package/dist/parser-5EHWYJMC.js.map +0 -1
  108. package/dist/parser-E6U5TNAU.cjs.map +0 -1
  109. package/dist/parser-UGB3NIVH.js.map +0 -1
  110. package/dist/provider-5K7O3Z2O.cjs.map +0 -1
  111. package/dist/provider-7H4CPZYS.js.map +0 -1
  112. package/dist/provider-H4WWSPOV.js.map +0 -1
  113. package/dist/render-P6663O4I.js +0 -10
  114. package/dist/seal-7PPTXKKV.js +0 -10
  115. package/dist/setup-QSJ2INNS.js.map +0 -1
  116. package/dist/watch-RMX427YR.js.map +0 -1
  117. /package/dist/{-6HWEFXVV.js.map → -AS4IABL2.js.map} +0 -0
  118. /package/dist/{detect-NTR2FUEG.js.map → chunks-WVMGF7JL.js.map} +0 -0
  119. /package/dist/{page-range-CIRRJPXJ.js.map → detect-YEZX2XCF.js.map} +0 -0
  120. /package/dist/{page-range-OF5I4PQY.js.map → page-range-737B4EZW.js.map} +0 -0
  121. /package/dist/{profile-io-CAKRPQRD.js.map → page-range-LNMXJU6W.js.map} +0 -0
  122. /package/dist/{render-P6663O4I.js.map → profile-io-PLDQFPJA.js.map} +0 -0
  123. /package/dist/{seal-7PPTXKKV.js.map → redact-7ILEAUTS.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -140,6 +140,10 @@ interface ParseOptions {
140
140
  onProgress?: (current: number, total: number) => void;
141
141
  /** PDF 머리글/바닥글 자동 제거 */
142
142
  removeHeaderFooter?: boolean;
143
+ /** 표 오른쪽 끝의 빈 열(서식 문서의 입력란) 보존 (#47).
144
+ * 기본 false: 마크다운 가독성을 위해 후행 빈 열을 트림.
145
+ * 양식 인식 경로(parse_form·fill)는 내부적으로 항상 켠다. */
146
+ keepTrailingEmptyCols?: boolean;
143
147
  /** 원본 파일 경로 (DRM COM fallback에 필요, 내부 전용) */
144
148
  filePath?: string;
145
149
  /**
@@ -231,7 +235,7 @@ interface PageQuality {
231
235
  replacementCharRatio: number;
232
236
  puaRatio: number;
233
237
  needsOcr: boolean;
234
- ocrReason?: "low_text" | "high_pua" | "high_control" | "high_replacement";
238
+ ocrReason?: "low_text" | "high_pua" | "high_control" | "high_replacement" | "garbled_hangul";
235
239
  }
236
240
  /** 문서 단위 품질 요약 (PDF 전용). */
237
241
  interface DocumentQualitySummary {
@@ -466,6 +470,8 @@ interface FillResult {
466
470
  filled: FormField[];
467
471
  /** 매칭 실패한 라벨 (입력에는 있지만 서식에서 못 찾은 것) */
468
472
  unmatched: string[];
473
+ /** 비치명 경고 (입력 라벨 정규화 충돌 등) — 없으면 생략 */
474
+ warnings?: string[];
469
475
  }
470
476
  /**
471
477
  * IRBlock[]에서 양식 필드를 찾아 값을 교체.
@@ -522,6 +528,8 @@ interface HwpxFillResult {
522
528
  filled: FormField[];
523
529
  /** 매칭 실패한 라벨 */
524
530
  unmatched: string[];
531
+ /** 비치명 경고 (입력 라벨 정규화 충돌 등) — 없으면 생략 */
532
+ warnings?: string[];
525
533
  }
526
534
  /**
527
535
  * HWPX 원본을 직접 수정하여 서식 필드를 채움 — 스타일 100% 보존.
@@ -1260,6 +1268,102 @@ interface ValidateResult {
1260
1268
  /** HWPX 버퍼의 컨테이너 구조를 검증한다. 문제가 없으면 ok=true. */
1261
1269
  declare function validateHwpx(buffer: ArrayBuffer | Uint8Array): Promise<ValidateResult>;
1262
1270
 
1271
+ /**
1272
+ * 한국 공문서 PII(개인정보) 탐지·마스킹 순수 로직.
1273
+ *
1274
+ * 텍스트 in → 마스킹된 텍스트 + 히트 리포트 out. 문서 파싱/patch는 기존 인프라가
1275
+ * 담당하고 여기서는 텍스트만 다룬다 (CLI/MCP 배선은 별도).
1276
+ *
1277
+ * 원칙:
1278
+ * - 서식 보존 마스킹 — 자릿수·구분자를 유지해 마스킹 전후 길이가 동일
1279
+ * - 히트 리포트에 원본 PII를 절대 담지 않는다 (`masked` 필드만 존재)
1280
+ * - 룰 우선순위 겹침 처리 — 우선순위순으로 매치를 수집하고, 이미 점유된
1281
+ * 구간과 겹치는 하위 룰 매치는 스킵 (RULE_PRIORITY 참조)
1282
+ * - 정규식은 모듈 로드 시 1회 컴파일 (matchAll은 내부 클론이라 lastIndex 안전)
1283
+ */
1284
+ type RedactRule = "rrn" | "phone" | "email" | "card" | "account" | "passport" | "driver";
1285
+ interface RedactHit {
1286
+ rule: RedactRule;
1287
+ /** 마스킹 후 문자열 — 원본 PII는 리포트에 담지 않는다 */
1288
+ masked: string;
1289
+ /** 원문 내 시작 오프셋 (UTF-16 단위) */
1290
+ index: number;
1291
+ /** 매치 길이 (서식 보존이라 마스킹 전후 동일) */
1292
+ length: number;
1293
+ }
1294
+ interface RedactTextResult {
1295
+ text: string;
1296
+ hits: RedactHit[];
1297
+ }
1298
+ interface RedactOptions {
1299
+ /** 적용할 룰 (기본: DEFAULT_REDACT_RULES — passport·driver는 기본 OFF) */
1300
+ rules?: RedactRule[];
1301
+ /** 마스크 문자 — 1글자(UTF-16 1단위), 영숫자 금지. 기본 "●" (마크다운 특수문자 아님) */
1302
+ maskChar?: string;
1303
+ }
1304
+ /** 기본 적용 룰 — passport(여권)·driver(운전면허)는 오탐 여지가 있어 opt-in */
1305
+ declare const DEFAULT_REDACT_RULES: readonly RedactRule[];
1306
+ /**
1307
+ * 텍스트에서 PII를 탐지해 서식 보존 마스킹.
1308
+ *
1309
+ * @param text - 대상 텍스트 (마크다운 포함)
1310
+ * @param options - 룰 선택·마스크 문자 (기본: rrn·phone·email·card·account, "●")
1311
+ * @returns 마스킹된 텍스트 + 히트 리포트 (index 오름차순, 원본 PII 미포함)
1312
+ */
1313
+ declare function redactText(text: string, options?: RedactOptions): RedactTextResult;
1314
+ /**
1315
+ * 마크다운 문서 전용 래퍼 — base64 이미지(data URI) 라인은 마스킹에서 제외한다.
1316
+ * base64 페이로드의 숫자열이 phone 등에 오탐되면 이미지가 깨지기 때문.
1317
+ * hits의 index는 문서 전체 기준 절대 오프셋으로 환산된다.
1318
+ */
1319
+ declare function redactMarkdown(markdown: string, options?: RedactOptions): RedactTextResult;
1320
+
1321
+ /**
1322
+ * RAG용 구조 보존 청킹 — IRBlock[] → DocChunk[].
1323
+ *
1324
+ * 문서의 위계(마크다운 헤딩 스택 + 개조식 리스트 깊이)를 breadcrumb으로 보존한
1325
+ * 청크 목록을 만든다. 토큰 상한·오버랩 등 자르기 정책은 의도적으로 없다 —
1326
+ * "구조 트리 제공"까지가 이 모듈의 몫이고 실제 분할은 소비자(RAG 파이프라인)가 한다.
1327
+ *
1328
+ * breadcrumb 규칙:
1329
+ * - 헤딩(level 1~6)은 스택 구조 — 같거나 깊은 level을 팝하고 push, 리스트 위계 리셋
1330
+ * - 리스트 항목은 깊이 d 등장 시 depth>=d를 팝하고 push — 하위 항목이 뒤따르면
1331
+ * 그 breadcrumb으로 승격되고, 자식이 없으면 다음 형제/헤딩이 팝해 자연 소멸
1332
+ * - 깊이는 IR의 listDepth 그대로. listDepth가 없는 개조식 선두 부호 문단
1333
+ * (□·○·- / 1.·가.·1) 등)은 depth 0 항목으로 취급 — IR에 없는 깊이는 지어내지 않는다
1334
+ * - 청크의 breadcrumb은 자기 자신을 제외한 상위 경로다
1335
+ */
1336
+
1337
+ interface DocChunk {
1338
+ /** "c0001" 순번 id — 같은 입력이면 같은 출력 (결정적) */
1339
+ id: string;
1340
+ type: "text" | "table" | "heading";
1341
+ /** 상위 헤딩 + 리스트 위계 경로 (예: ["1. 개요", "가. 목적"]) */
1342
+ breadcrumb: string[];
1343
+ /** 청크 본문 마크다운 — 표는 GFM/HTML 그대로 (blocksToMarkdown 재사용) */
1344
+ text: string;
1345
+ /** 원본 페이지/섹션 번호 (1-based) — IR에 없으면 생략 */
1346
+ page?: number;
1347
+ /** 원본 IRBlock 인덱스 범위 [start, end] (양끝 포함) — 출처 앵커 */
1348
+ blockRange: [number, number];
1349
+ /** 표 청크 전용 구조 요약 — cells는 includeTableCells 옵션 시에만 */
1350
+ table?: {
1351
+ rows: number;
1352
+ cols: number;
1353
+ cells?: string[][];
1354
+ };
1355
+ }
1356
+ interface ChunkOptions {
1357
+ /** 표 청크에 셀 텍스트 행렬 포함 여부 (기본 false) */
1358
+ includeTableCells?: boolean;
1359
+ /**
1360
+ * "section"(기본): 같은 breadcrumb 아래 연속 텍스트 블록을 하나로 병합,
1361
+ * "block": IRBlock 1개 = 청크 1개
1362
+ */
1363
+ granularity?: "block" | "section";
1364
+ }
1365
+ declare function blocksToChunks(blocks: IRBlock[], options?: ChunkOptions): DocChunk[];
1366
+
1263
1367
  /**
1264
1368
  * HWPX 문서 세션 — 에디터 통합용 블록 단위 증분 패치 API (v3.1).
1265
1369
  *
@@ -1556,4 +1660,4 @@ interface FillFormOutput {
1556
1660
  */
1557
1661
  declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillInput>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1558
1662
 
1559
- export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type DiffChangeType, type DiffResult, 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 PageQuality, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PatchOptions, type PatchResult, type PatchSkip, type PlaceSealResult, type PrintOptions, type PrintPreset, 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, blocksToMarkdown, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, 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, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, validateHwpx };
1663
+ export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type ChunkOptions, 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 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, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, 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, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, redactMarkdown, redactText, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, validateHwpx };
package/dist/index.d.ts CHANGED
@@ -140,6 +140,10 @@ interface ParseOptions {
140
140
  onProgress?: (current: number, total: number) => void;
141
141
  /** PDF 머리글/바닥글 자동 제거 */
142
142
  removeHeaderFooter?: boolean;
143
+ /** 표 오른쪽 끝의 빈 열(서식 문서의 입력란) 보존 (#47).
144
+ * 기본 false: 마크다운 가독성을 위해 후행 빈 열을 트림.
145
+ * 양식 인식 경로(parse_form·fill)는 내부적으로 항상 켠다. */
146
+ keepTrailingEmptyCols?: boolean;
143
147
  /** 원본 파일 경로 (DRM COM fallback에 필요, 내부 전용) */
144
148
  filePath?: string;
145
149
  /**
@@ -231,7 +235,7 @@ interface PageQuality {
231
235
  replacementCharRatio: number;
232
236
  puaRatio: number;
233
237
  needsOcr: boolean;
234
- ocrReason?: "low_text" | "high_pua" | "high_control" | "high_replacement";
238
+ ocrReason?: "low_text" | "high_pua" | "high_control" | "high_replacement" | "garbled_hangul";
235
239
  }
236
240
  /** 문서 단위 품질 요약 (PDF 전용). */
237
241
  interface DocumentQualitySummary {
@@ -466,6 +470,8 @@ interface FillResult {
466
470
  filled: FormField[];
467
471
  /** 매칭 실패한 라벨 (입력에는 있지만 서식에서 못 찾은 것) */
468
472
  unmatched: string[];
473
+ /** 비치명 경고 (입력 라벨 정규화 충돌 등) — 없으면 생략 */
474
+ warnings?: string[];
469
475
  }
470
476
  /**
471
477
  * IRBlock[]에서 양식 필드를 찾아 값을 교체.
@@ -522,6 +528,8 @@ interface HwpxFillResult {
522
528
  filled: FormField[];
523
529
  /** 매칭 실패한 라벨 */
524
530
  unmatched: string[];
531
+ /** 비치명 경고 (입력 라벨 정규화 충돌 등) — 없으면 생략 */
532
+ warnings?: string[];
525
533
  }
526
534
  /**
527
535
  * HWPX 원본을 직접 수정하여 서식 필드를 채움 — 스타일 100% 보존.
@@ -1260,6 +1268,102 @@ interface ValidateResult {
1260
1268
  /** HWPX 버퍼의 컨테이너 구조를 검증한다. 문제가 없으면 ok=true. */
1261
1269
  declare function validateHwpx(buffer: ArrayBuffer | Uint8Array): Promise<ValidateResult>;
1262
1270
 
1271
+ /**
1272
+ * 한국 공문서 PII(개인정보) 탐지·마스킹 순수 로직.
1273
+ *
1274
+ * 텍스트 in → 마스킹된 텍스트 + 히트 리포트 out. 문서 파싱/patch는 기존 인프라가
1275
+ * 담당하고 여기서는 텍스트만 다룬다 (CLI/MCP 배선은 별도).
1276
+ *
1277
+ * 원칙:
1278
+ * - 서식 보존 마스킹 — 자릿수·구분자를 유지해 마스킹 전후 길이가 동일
1279
+ * - 히트 리포트에 원본 PII를 절대 담지 않는다 (`masked` 필드만 존재)
1280
+ * - 룰 우선순위 겹침 처리 — 우선순위순으로 매치를 수집하고, 이미 점유된
1281
+ * 구간과 겹치는 하위 룰 매치는 스킵 (RULE_PRIORITY 참조)
1282
+ * - 정규식은 모듈 로드 시 1회 컴파일 (matchAll은 내부 클론이라 lastIndex 안전)
1283
+ */
1284
+ type RedactRule = "rrn" | "phone" | "email" | "card" | "account" | "passport" | "driver";
1285
+ interface RedactHit {
1286
+ rule: RedactRule;
1287
+ /** 마스킹 후 문자열 — 원본 PII는 리포트에 담지 않는다 */
1288
+ masked: string;
1289
+ /** 원문 내 시작 오프셋 (UTF-16 단위) */
1290
+ index: number;
1291
+ /** 매치 길이 (서식 보존이라 마스킹 전후 동일) */
1292
+ length: number;
1293
+ }
1294
+ interface RedactTextResult {
1295
+ text: string;
1296
+ hits: RedactHit[];
1297
+ }
1298
+ interface RedactOptions {
1299
+ /** 적용할 룰 (기본: DEFAULT_REDACT_RULES — passport·driver는 기본 OFF) */
1300
+ rules?: RedactRule[];
1301
+ /** 마스크 문자 — 1글자(UTF-16 1단위), 영숫자 금지. 기본 "●" (마크다운 특수문자 아님) */
1302
+ maskChar?: string;
1303
+ }
1304
+ /** 기본 적용 룰 — passport(여권)·driver(운전면허)는 오탐 여지가 있어 opt-in */
1305
+ declare const DEFAULT_REDACT_RULES: readonly RedactRule[];
1306
+ /**
1307
+ * 텍스트에서 PII를 탐지해 서식 보존 마스킹.
1308
+ *
1309
+ * @param text - 대상 텍스트 (마크다운 포함)
1310
+ * @param options - 룰 선택·마스크 문자 (기본: rrn·phone·email·card·account, "●")
1311
+ * @returns 마스킹된 텍스트 + 히트 리포트 (index 오름차순, 원본 PII 미포함)
1312
+ */
1313
+ declare function redactText(text: string, options?: RedactOptions): RedactTextResult;
1314
+ /**
1315
+ * 마크다운 문서 전용 래퍼 — base64 이미지(data URI) 라인은 마스킹에서 제외한다.
1316
+ * base64 페이로드의 숫자열이 phone 등에 오탐되면 이미지가 깨지기 때문.
1317
+ * hits의 index는 문서 전체 기준 절대 오프셋으로 환산된다.
1318
+ */
1319
+ declare function redactMarkdown(markdown: string, options?: RedactOptions): RedactTextResult;
1320
+
1321
+ /**
1322
+ * RAG용 구조 보존 청킹 — IRBlock[] → DocChunk[].
1323
+ *
1324
+ * 문서의 위계(마크다운 헤딩 스택 + 개조식 리스트 깊이)를 breadcrumb으로 보존한
1325
+ * 청크 목록을 만든다. 토큰 상한·오버랩 등 자르기 정책은 의도적으로 없다 —
1326
+ * "구조 트리 제공"까지가 이 모듈의 몫이고 실제 분할은 소비자(RAG 파이프라인)가 한다.
1327
+ *
1328
+ * breadcrumb 규칙:
1329
+ * - 헤딩(level 1~6)은 스택 구조 — 같거나 깊은 level을 팝하고 push, 리스트 위계 리셋
1330
+ * - 리스트 항목은 깊이 d 등장 시 depth>=d를 팝하고 push — 하위 항목이 뒤따르면
1331
+ * 그 breadcrumb으로 승격되고, 자식이 없으면 다음 형제/헤딩이 팝해 자연 소멸
1332
+ * - 깊이는 IR의 listDepth 그대로. listDepth가 없는 개조식 선두 부호 문단
1333
+ * (□·○·- / 1.·가.·1) 등)은 depth 0 항목으로 취급 — IR에 없는 깊이는 지어내지 않는다
1334
+ * - 청크의 breadcrumb은 자기 자신을 제외한 상위 경로다
1335
+ */
1336
+
1337
+ interface DocChunk {
1338
+ /** "c0001" 순번 id — 같은 입력이면 같은 출력 (결정적) */
1339
+ id: string;
1340
+ type: "text" | "table" | "heading";
1341
+ /** 상위 헤딩 + 리스트 위계 경로 (예: ["1. 개요", "가. 목적"]) */
1342
+ breadcrumb: string[];
1343
+ /** 청크 본문 마크다운 — 표는 GFM/HTML 그대로 (blocksToMarkdown 재사용) */
1344
+ text: string;
1345
+ /** 원본 페이지/섹션 번호 (1-based) — IR에 없으면 생략 */
1346
+ page?: number;
1347
+ /** 원본 IRBlock 인덱스 범위 [start, end] (양끝 포함) — 출처 앵커 */
1348
+ blockRange: [number, number];
1349
+ /** 표 청크 전용 구조 요약 — cells는 includeTableCells 옵션 시에만 */
1350
+ table?: {
1351
+ rows: number;
1352
+ cols: number;
1353
+ cells?: string[][];
1354
+ };
1355
+ }
1356
+ interface ChunkOptions {
1357
+ /** 표 청크에 셀 텍스트 행렬 포함 여부 (기본 false) */
1358
+ includeTableCells?: boolean;
1359
+ /**
1360
+ * "section"(기본): 같은 breadcrumb 아래 연속 텍스트 블록을 하나로 병합,
1361
+ * "block": IRBlock 1개 = 청크 1개
1362
+ */
1363
+ granularity?: "block" | "section";
1364
+ }
1365
+ declare function blocksToChunks(blocks: IRBlock[], options?: ChunkOptions): DocChunk[];
1366
+
1263
1367
  /**
1264
1368
  * HWPX 문서 세션 — 에디터 통합용 블록 단위 증분 패치 API (v3.1).
1265
1369
  *
@@ -1556,4 +1660,4 @@ interface FillFormOutput {
1556
1660
  */
1557
1661
  declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillInput>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1558
1662
 
1559
- export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type DiffChangeType, type DiffResult, 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 PageQuality, type ParseFailure, type ParseOptions, type ParseResult, type ParseSuccess, type ParseWarning, type PatchOptions, type PatchResult, type PatchSkip, type PlaceSealResult, type PrintOptions, type PrintPreset, 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, blocksToMarkdown, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, 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, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, validateHwpx };
1663
+ export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BorderDef, type BorderFillDef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, type CellProfile, type CharPrDef, type ChunkOptions, 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 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, blocksToPdf, buildParagraphSplices, buildRangeSplices, charWidthEm1000, compare, detectFormat, detectOle2Format, detectZipFormat, diffBlocks, 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, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, redactMarkdown, redactText, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord, unknownFontWarnings, validateHwpx };