kordoc 3.13.0 → 3.16.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 (54) hide show
  1. package/README.md +34 -1
  2. package/dist/{-MRPDPE2X.js → -H7N62NZU.js} +24 -13
  3. package/dist/{chunk-33CIKNL4.js → chunk-5RHRQ7HK.js} +479 -258
  4. package/dist/chunk-5RHRQ7HK.js.map +1 -0
  5. package/dist/{chunk-MEXUFQVC.cjs → chunk-BIP4JAVG.cjs} +5 -5
  6. package/dist/chunk-BIP4JAVG.cjs.map +1 -0
  7. package/dist/chunk-DCZVOIEO.cjs.map +1 -1
  8. package/dist/chunk-FGL7BH4P.js +1019 -0
  9. package/dist/chunk-FGL7BH4P.js.map +1 -0
  10. package/dist/chunk-GS7T56RP.cjs.map +1 -1
  11. package/dist/{chunk-Q6UXVJXI.js → chunk-IC56KHBL.js} +2 -2
  12. package/dist/chunk-JFNWJFKP.js +185 -0
  13. package/dist/chunk-JFNWJFKP.js.map +1 -0
  14. package/dist/{chunk-YXOT7P5B.js → chunk-LYL4IL3E.js} +5 -5
  15. package/dist/{chunk-YXOT7P5B.js.map → chunk-LYL4IL3E.js.map} +1 -1
  16. package/dist/{chunk-O4WFPOFN.js → chunk-Q7EGGW3H.js} +5 -5
  17. package/dist/{chunk-O4WFPOFN.js.map → chunk-Q7EGGW3H.js.map} +1 -1
  18. package/dist/{chunk-TWACKS3K.js → chunk-WD5NUUU6.js} +571 -729
  19. package/dist/chunk-WD5NUUU6.js.map +1 -0
  20. package/dist/cli.js +125 -12
  21. package/dist/cli.js.map +1 -1
  22. package/dist/formula-5NKVS2LR.cjs.map +1 -1
  23. package/dist/index.cjs +1668 -449
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +144 -6
  26. package/dist/index.d.ts +144 -6
  27. package/dist/index.js +1502 -283
  28. package/dist/index.js.map +1 -1
  29. package/dist/mcp.js +93 -12
  30. package/dist/mcp.js.map +1 -1
  31. package/dist/page-range-P7SDW6LR.cjs.map +1 -1
  32. package/dist/{parser-Z3IL2ESY.js → parser-5G247XYD.js} +54 -6
  33. package/dist/parser-5G247XYD.js.map +1 -0
  34. package/dist/{parser-DZBI3EA2.cjs → parser-6V7F3GET.cjs} +66 -18
  35. package/dist/parser-6V7F3GET.cjs.map +1 -0
  36. package/dist/{parser-XUNGOH76.js → parser-HBHCD7TE.js} +55 -7
  37. package/dist/parser-HBHCD7TE.js.map +1 -0
  38. package/dist/provider-G4C2V2PD.cjs.map +1 -1
  39. package/dist/render-VA4NHROW.js +10 -0
  40. package/dist/seal-UVDRGHEF.js +10 -0
  41. package/dist/seal-UVDRGHEF.js.map +1 -0
  42. package/dist/{watch-G5NFIT5L.js → watch-HIYNOSFD.js} +7 -5
  43. package/dist/{watch-G5NFIT5L.js.map → watch-HIYNOSFD.js.map} +1 -1
  44. package/package.json +4 -3
  45. package/dist/chunk-33CIKNL4.js.map +0 -1
  46. package/dist/chunk-MEXUFQVC.cjs.map +0 -1
  47. package/dist/chunk-TWACKS3K.js.map +0 -1
  48. package/dist/parser-DZBI3EA2.cjs.map +0 -1
  49. package/dist/parser-XUNGOH76.js.map +0 -1
  50. package/dist/parser-Z3IL2ESY.js.map +0 -1
  51. package/dist/render-VZ4OGHZU.js +0 -9
  52. /package/dist/{-MRPDPE2X.js.map → -H7N62NZU.js.map} +0 -0
  53. /package/dist/{chunk-Q6UXVJXI.js.map → chunk-IC56KHBL.js.map} +0 -0
  54. /package/dist/{render-VZ4OGHZU.js.map → render-VA4NHROW.js.map} +0 -0
package/dist/index.d.cts CHANGED
@@ -296,6 +296,8 @@ interface FormField {
296
296
  row: number;
297
297
  /** 0-based 소스 열 */
298
298
  col: number;
299
+ /** 매칭된 입력 키(정규화) — 모호 라벨 거부 가드(fillWithUniqueGuard)의 집계 기준 */
300
+ key?: string;
299
301
  }
300
302
  interface FormResult {
301
303
  fields: FormField[];
@@ -319,6 +321,21 @@ interface WatchOptions {
319
321
  * 배열이면 등장 순서대로 하나씩 소진(2~30장 반복 양식·명부형 표).
320
322
  */
321
323
  type FillValue = string | string[];
324
+ /**
325
+ * 채울 값 입력 — 값만 주거나, 서식 변환(format)을 함께 지정한다.
326
+ * 프로필엔 정준값 하나(생년월일 "19900315"), 서식마다 모양이 다를 때
327
+ * format이 도구 안에서 변환한다 (claw-hwp secure-fill 포맷엔진 이식).
328
+ */
329
+ type FillInput = FillValue | {
330
+ value: FillValue;
331
+ format?: string;
332
+ };
333
+ /**
334
+ * 값 서식 변환 — `종류:스타일` 접두형(date:/phone:/rrn:/mask:/digits/upper/lower/nospace)
335
+ * 또는 접두 없는 자유 패턴(`#` 포함 → 숫자마스크, yyyy·yy·mm·dd 포함 → 날짜 토큰).
336
+ * 모르는 포맷은 값 원형 반환 (fail-open — 채움 자체는 진행).
337
+ */
338
+ declare function formatFillValue(value: string, format?: string): string;
322
339
  /**
323
340
  * 다중값 커서 — 라벨별 값 소비 상태를 추적한다.
324
341
  * 스칼라 값은 무한 반복(기존 동작), 배열 값은 적용 순서대로 소진되며
@@ -338,6 +355,20 @@ declare class ValueCursor {
338
355
  /** 값 소비 — 배열이면 커서 전진, 소진 시 undefined */
339
356
  consume(key: string): string | undefined;
340
357
  }
358
+ /**
359
+ * 모호 라벨 거부 가드 — 한 입력 키(스칼라)가 서식의 2곳 이상에 채워지면 남의 블록
360
+ * 오염 위험(대표자 행에 참여인력 값이 들어가는 류)이므로, 그 키는 채우지 않고
361
+ * rejected로 보고한 뒤 나머지 키만으로 다시 채운다 (claw-hwp require_occurrence 이식).
362
+ * 배열 값은 다중 등장 소진이 의도된 동작이라 거부 대상이 아니다.
363
+ * @param run 같은 원본에 대해 결정적으로 재실행 가능한 채우기 함수
364
+ */
365
+ declare function fillWithUniqueGuard<R extends {
366
+ filled: Array<{
367
+ key?: string;
368
+ }>;
369
+ }>(values: Record<string, FillInput>, run: (vals: Record<string, FillInput>) => R | Promise<R>): Promise<R & {
370
+ rejected: string[];
371
+ }>;
341
372
 
342
373
  /** 문서 비교 엔진 — IR 레벨 블록 비교로 신구대조표 생성 */
343
374
 
@@ -412,7 +443,7 @@ interface FillResult {
412
443
  * })
413
444
  * ```
414
445
  */
415
- declare function fillFormFields(blocks: IRBlock[], values: Record<string, FillValue>): FillResult;
446
+ declare function fillFormFields(blocks: IRBlock[], values: Record<string, FillInput>): FillResult;
416
447
 
417
448
  /**
418
449
  * HWPX 원본 서식 유지 채우기 — section XML 오프셋 splice (v3.1, 바이트 보존)
@@ -455,7 +486,71 @@ interface HwpxFillResult {
455
486
  * 문자열이면 기존처럼 모든 등장에 동일값.
456
487
  * @returns HwpxFillResult
457
488
  */
458
- declare function fillHwpx(hwpxBuffer: ArrayBuffer, values: Record<string, FillValue>): Promise<HwpxFillResult>;
489
+ declare function fillHwpx(hwpxBuffer: ArrayBuffer, values: Record<string, FillInput>): Promise<HwpxFillResult>;
490
+
491
+ /**
492
+ * place_seal — 도장/서명 이미지를 앵커 문구("(인)"·"서명 또는 인" 등) 위에
493
+ * 부유(글 앞) 배치. 표/페이지 불확장 (P6, claw-hwp placeSeal 이식).
494
+ *
495
+ * 원리:
496
+ * - 앵커 문구가 든 문단을 찾아 그 문단에 <hp:pic> 부유 개체를 anchor 한다.
497
+ * 핵심 속성: treatAsChar="0" + flowWithText="0" + allowOverlap="1" +
498
+ * textWrap="IN_FRONT_OF_TEXT" — flowWithText="1"이면 한컴이 개체 높이만큼
499
+ * 셀/페이지를 키운다 (claw-hwp GT 검증 규칙).
500
+ * - 수평 위치는 폰트 메트릭으로 계산: 전각(한글/CJK)=1em, ASCII·반각=0.5em,
501
+ * em = 앵커 run charPr 높이(1/100pt). 렌더 없이 배치하고 렌더는 검증용.
502
+ * - 가운데/오른쪽 정렬 문단(서식 셀에 흔함)은 블록 전체가 밀리므로
503
+ * (사용가능폭 − 문단폭)의 정렬 이동분을 x에 더한다.
504
+ * - 위치 프레임은 PARA(문단 좌상단 기준) — 한컴은 문단 위로는 못 올라가게
505
+ * 클램프하므로, 여유 공간이 있는 표 셀에서는 줄 세로 중앙에 앉고 본문
506
+ * 최상단 줄에서는 상단 정렬로 눕는다.
507
+ *
508
+ * 적용 범위: 본문/표 셀/글상자 문단 (머리말·꼬리말·각주 내 앵커는 제외).
509
+ * ZIP 재조립은 patchZipEntries — 비변경 엔트리는 1바이트도 건드리지 않고,
510
+ * 도장 PNG는 BinData 신규 엔트리 + manifest(opf:item) 등재로 추가한다.
511
+ */
512
+ /** 도장 배치 요청 */
513
+ interface SealOp {
514
+ /** 앵커 문구 (예: "(인)", "서명 또는 인") */
515
+ anchor: string;
516
+ /** 같은 앵커가 여럿일 때 0-based 선택 (기본 0) */
517
+ occurrence?: number;
518
+ /** 도장/서명 이미지 바이트 (투명 배경 PNG 권장) */
519
+ image: Uint8Array;
520
+ /** 이미지 확장자 (기본 png) */
521
+ ext?: "png" | "jpg" | "jpeg" | "bmp" | "gif";
522
+ /** 도장 한 변 크기 mm (기본: 줄높이×1.6, 7~18mm 클램프) */
523
+ sizeMm?: number;
524
+ /** overlap=문구 위에 겹침, right=문구 오른쪽 옆, auto=공간 있으면 right (기본 auto) */
525
+ mode?: "overlap" | "right" | "auto";
526
+ /** 미세조정 mm */
527
+ dxMm?: number;
528
+ dyMm?: number;
529
+ }
530
+ /** 배치 결과 (도장 1개당 1건) */
531
+ interface SealPlacement {
532
+ anchor: string;
533
+ occurrence: number;
534
+ sectionIndex: number;
535
+ mode: "overlap" | "right";
536
+ posXMm: number;
537
+ posYMm: number;
538
+ sizeMm: number;
539
+ /** ZIP에 추가된 이미지 파트 경로 (BinData/imageN.ext) */
540
+ entry: string;
541
+ }
542
+ interface PlaceSealResult {
543
+ buffer: ArrayBuffer;
544
+ placed: SealPlacement[];
545
+ }
546
+ /**
547
+ * HWPX에 도장/서명 이미지를 앵커 문구 기준으로 부유 배치한다.
548
+ *
549
+ * @param hwpxBuffer 원본 HWPX
550
+ * @param ops 도장 배치 요청 (여러 개 가능 — 같은 이미지 재사용 시에도 op마다 파트가 추가됨)
551
+ * @throws KordocError 앵커 미발견 (본문 내 등장 횟수를 메시지에 포함)
552
+ */
553
+ declare function placeSealHwpx(hwpxBuffer: ArrayBuffer, ops: SealOp[]): Promise<PlaceSealResult>;
459
554
 
460
555
  /**
461
556
  * 공문서(公文書) 모드 — 한국 행정 공문서 표준 서식 렌더링 로직
@@ -802,6 +897,33 @@ declare function patchHwpx(original: Uint8Array, editedMarkdown: string, options
802
897
  */
803
898
  declare function patchHwp(original: Uint8Array, editedMarkdown: string, options?: PatchOptions): Promise<PatchResult>;
804
899
 
900
+ /**
901
+ * HWPX 구조 검증 — 한컴오피스/한컴독스가 열기를 거부하는 컨테이너 결함을 사전에 잡는다.
902
+ *
903
+ * 검사 항목 (claw-hwp validate.py의 실측 검사셋 이식 — MIT © DoHyun468/claw-hwp):
904
+ * - 유효한 ZIP인지, mimetype이 첫 엔트리이고 내용이 application/hwp+zip인지
905
+ * - 필수 파일 존재 (META-INF/container.xml, content.hpf, header.xml, section0.xml)
906
+ * - XML/HPF/RDF 엔트리 웰폼드
907
+ * - header.xml secCnt == 실제 Contents/sectionN.xml 수
908
+ * (한컴독스는 실제 파일 목록이 아니라 secCnt를 신뢰하고, 불일치 시 열기를 거부한다)
909
+ * - content.hpf manifest의 <opf:item href>가 전부 실존하는지
910
+ */
911
+ /** 검증에서 발견된 문제 하나 */
912
+ interface ValidateIssue {
913
+ /** 문제가 발견된 zip 내부 경로 (컨테이너 전역 문제면 생략) */
914
+ path?: string;
915
+ message: string;
916
+ }
917
+ /** validateHwpx 결과 */
918
+ interface ValidateResult {
919
+ ok: boolean;
920
+ issues: ValidateIssue[];
921
+ /** 검사한 zip 엔트리 수 (디렉토리 제외) */
922
+ entryCount: number;
923
+ }
924
+ /** HWPX 버퍼의 컨테이너 구조를 검증한다. 문제가 없으면 ok=true. */
925
+ declare function validateHwpx(buffer: ArrayBuffer | Uint8Array): Promise<ValidateResult>;
926
+
805
927
  /**
806
928
  * HWPX 문서 세션 — 에디터 통합용 블록 단위 증분 패치 API (v3.1).
807
929
  *
@@ -955,17 +1077,33 @@ declare function blocksToPdf(blocks: IRBlock[], options?: PrintOptions): Promise
955
1077
  * - 좌표 속성엔 uint32로 저장된 음수가 섞여 있다(toInt32 필수).
956
1078
  * - 표 열은 span 제약 경계 전파로, 행은 rs=1 max + 콘텐츠 초과 성장으로 푼다.
957
1079
  *
958
- * 범위: 1페이지(section0) 한정, 수식·그리기개체 도형은 미지원(경고 수집).
1080
+ * 페이지: 최상위 lineseg vertpos는 페이지 로컬(페이지마다 0부터 리셋)이므로 역행
1081
+ * 지점을 페이지 경계로 감지, 전 페이지를 세로 스택으로 그린다(페이지별 흰 배경 +
1082
+ * 클립). 페이지에 걸친 표는 시작 페이지에서 잘린다(조판 캐시에 분할점이 없음).
1083
+ *
1084
+ * 범위: section0 한정(다중 구역은 첫 구역만), 수식·그리기개체 도형은 미지원(경고 수집).
959
1085
  */
1086
+
960
1087
  interface RenderSvgOptions {
961
1088
  /** 이미지 1장당 허용 최대 바이트 (기본 40MB) */
962
1089
  maxImageBytes?: number;
1090
+ /** 검색어 형광펜 — 텍스트 조각 내 매치 구간에 배경 rect (대소문자 무시).
1091
+ * charPr(스타일) 경계에 걸친 매치는 칠하지 못한다. */
1092
+ highlights?: string[];
1093
+ /** Tier-2 reflow — 조판 캐시(linesegarray) 없는 파일도 순수 TS 조판으로 렌더.
1094
+ * 캐시가 있으면 무시(한컴본은 캐시 재생). 기본 false(캐시 없으면 KordocError). */
1095
+ reflow?: boolean;
1096
+ /** reflow 줄바꿈 모드 — 'keep'(어절, Windows 한글·공문서) / 'charAll'(글자, macOS·전자결재) */
1097
+ reflowMode?: WrapMode;
963
1098
  }
964
1099
  interface RenderSvgResult {
965
1100
  svg: string;
966
- /** 페이지 크기 (pt) */
1101
+ /** 페이지 (pt) */
967
1102
  width: number;
1103
+ /** 전체 캔버스 높이 (pt) — 페이지 세로 스택 + 간격 */
968
1104
  height: number;
1105
+ /** 렌더된 페이지 수 */
1106
+ pageCount: number;
969
1107
  warnings: string[];
970
1108
  stats: {
971
1109
  texts: number;
@@ -1077,6 +1215,6 @@ interface FillFormOutput {
1077
1215
  * console.log(result.output) // 채워진 마크다운
1078
1216
  * ```
1079
1217
  */
1080
- declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillValue>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1218
+ declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillInput>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1081
1219
 
1082
- export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, type DiffChangeType, type DiffResult, type DocumentMetadata, type DocumentQualitySummary, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillOutputFormat, type FillResult, type FillValue, type FormField, type FormFieldSchema, type FormFieldType, type FormResult, type FormSchemaResult, type GongmunFont, 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 PrintOptions, type PrintPreset, type RenderSvgOptions, type RenderSvgResult, SPACE_EM_FIXED, SPACE_EM_FONT, type ScanCell, type ScanParaKind, type ScanParagraph, type ScanTable, type SectionScan, type SpliceEdit, type TRange, VERSION, 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, fitRatioForFewerLines, inferFieldType, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, measureTextWidth, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord };
1220
+ export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, 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 GongmunFont, 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, 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, inferFieldType, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, measureTextWidth, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord, validateHwpx };
package/dist/index.d.ts CHANGED
@@ -296,6 +296,8 @@ interface FormField {
296
296
  row: number;
297
297
  /** 0-based 소스 열 */
298
298
  col: number;
299
+ /** 매칭된 입력 키(정규화) — 모호 라벨 거부 가드(fillWithUniqueGuard)의 집계 기준 */
300
+ key?: string;
299
301
  }
300
302
  interface FormResult {
301
303
  fields: FormField[];
@@ -319,6 +321,21 @@ interface WatchOptions {
319
321
  * 배열이면 등장 순서대로 하나씩 소진(2~30장 반복 양식·명부형 표).
320
322
  */
321
323
  type FillValue = string | string[];
324
+ /**
325
+ * 채울 값 입력 — 값만 주거나, 서식 변환(format)을 함께 지정한다.
326
+ * 프로필엔 정준값 하나(생년월일 "19900315"), 서식마다 모양이 다를 때
327
+ * format이 도구 안에서 변환한다 (claw-hwp secure-fill 포맷엔진 이식).
328
+ */
329
+ type FillInput = FillValue | {
330
+ value: FillValue;
331
+ format?: string;
332
+ };
333
+ /**
334
+ * 값 서식 변환 — `종류:스타일` 접두형(date:/phone:/rrn:/mask:/digits/upper/lower/nospace)
335
+ * 또는 접두 없는 자유 패턴(`#` 포함 → 숫자마스크, yyyy·yy·mm·dd 포함 → 날짜 토큰).
336
+ * 모르는 포맷은 값 원형 반환 (fail-open — 채움 자체는 진행).
337
+ */
338
+ declare function formatFillValue(value: string, format?: string): string;
322
339
  /**
323
340
  * 다중값 커서 — 라벨별 값 소비 상태를 추적한다.
324
341
  * 스칼라 값은 무한 반복(기존 동작), 배열 값은 적용 순서대로 소진되며
@@ -338,6 +355,20 @@ declare class ValueCursor {
338
355
  /** 값 소비 — 배열이면 커서 전진, 소진 시 undefined */
339
356
  consume(key: string): string | undefined;
340
357
  }
358
+ /**
359
+ * 모호 라벨 거부 가드 — 한 입력 키(스칼라)가 서식의 2곳 이상에 채워지면 남의 블록
360
+ * 오염 위험(대표자 행에 참여인력 값이 들어가는 류)이므로, 그 키는 채우지 않고
361
+ * rejected로 보고한 뒤 나머지 키만으로 다시 채운다 (claw-hwp require_occurrence 이식).
362
+ * 배열 값은 다중 등장 소진이 의도된 동작이라 거부 대상이 아니다.
363
+ * @param run 같은 원본에 대해 결정적으로 재실행 가능한 채우기 함수
364
+ */
365
+ declare function fillWithUniqueGuard<R extends {
366
+ filled: Array<{
367
+ key?: string;
368
+ }>;
369
+ }>(values: Record<string, FillInput>, run: (vals: Record<string, FillInput>) => R | Promise<R>): Promise<R & {
370
+ rejected: string[];
371
+ }>;
341
372
 
342
373
  /** 문서 비교 엔진 — IR 레벨 블록 비교로 신구대조표 생성 */
343
374
 
@@ -412,7 +443,7 @@ interface FillResult {
412
443
  * })
413
444
  * ```
414
445
  */
415
- declare function fillFormFields(blocks: IRBlock[], values: Record<string, FillValue>): FillResult;
446
+ declare function fillFormFields(blocks: IRBlock[], values: Record<string, FillInput>): FillResult;
416
447
 
417
448
  /**
418
449
  * HWPX 원본 서식 유지 채우기 — section XML 오프셋 splice (v3.1, 바이트 보존)
@@ -455,7 +486,71 @@ interface HwpxFillResult {
455
486
  * 문자열이면 기존처럼 모든 등장에 동일값.
456
487
  * @returns HwpxFillResult
457
488
  */
458
- declare function fillHwpx(hwpxBuffer: ArrayBuffer, values: Record<string, FillValue>): Promise<HwpxFillResult>;
489
+ declare function fillHwpx(hwpxBuffer: ArrayBuffer, values: Record<string, FillInput>): Promise<HwpxFillResult>;
490
+
491
+ /**
492
+ * place_seal — 도장/서명 이미지를 앵커 문구("(인)"·"서명 또는 인" 등) 위에
493
+ * 부유(글 앞) 배치. 표/페이지 불확장 (P6, claw-hwp placeSeal 이식).
494
+ *
495
+ * 원리:
496
+ * - 앵커 문구가 든 문단을 찾아 그 문단에 <hp:pic> 부유 개체를 anchor 한다.
497
+ * 핵심 속성: treatAsChar="0" + flowWithText="0" + allowOverlap="1" +
498
+ * textWrap="IN_FRONT_OF_TEXT" — flowWithText="1"이면 한컴이 개체 높이만큼
499
+ * 셀/페이지를 키운다 (claw-hwp GT 검증 규칙).
500
+ * - 수평 위치는 폰트 메트릭으로 계산: 전각(한글/CJK)=1em, ASCII·반각=0.5em,
501
+ * em = 앵커 run charPr 높이(1/100pt). 렌더 없이 배치하고 렌더는 검증용.
502
+ * - 가운데/오른쪽 정렬 문단(서식 셀에 흔함)은 블록 전체가 밀리므로
503
+ * (사용가능폭 − 문단폭)의 정렬 이동분을 x에 더한다.
504
+ * - 위치 프레임은 PARA(문단 좌상단 기준) — 한컴은 문단 위로는 못 올라가게
505
+ * 클램프하므로, 여유 공간이 있는 표 셀에서는 줄 세로 중앙에 앉고 본문
506
+ * 최상단 줄에서는 상단 정렬로 눕는다.
507
+ *
508
+ * 적용 범위: 본문/표 셀/글상자 문단 (머리말·꼬리말·각주 내 앵커는 제외).
509
+ * ZIP 재조립은 patchZipEntries — 비변경 엔트리는 1바이트도 건드리지 않고,
510
+ * 도장 PNG는 BinData 신규 엔트리 + manifest(opf:item) 등재로 추가한다.
511
+ */
512
+ /** 도장 배치 요청 */
513
+ interface SealOp {
514
+ /** 앵커 문구 (예: "(인)", "서명 또는 인") */
515
+ anchor: string;
516
+ /** 같은 앵커가 여럿일 때 0-based 선택 (기본 0) */
517
+ occurrence?: number;
518
+ /** 도장/서명 이미지 바이트 (투명 배경 PNG 권장) */
519
+ image: Uint8Array;
520
+ /** 이미지 확장자 (기본 png) */
521
+ ext?: "png" | "jpg" | "jpeg" | "bmp" | "gif";
522
+ /** 도장 한 변 크기 mm (기본: 줄높이×1.6, 7~18mm 클램프) */
523
+ sizeMm?: number;
524
+ /** overlap=문구 위에 겹침, right=문구 오른쪽 옆, auto=공간 있으면 right (기본 auto) */
525
+ mode?: "overlap" | "right" | "auto";
526
+ /** 미세조정 mm */
527
+ dxMm?: number;
528
+ dyMm?: number;
529
+ }
530
+ /** 배치 결과 (도장 1개당 1건) */
531
+ interface SealPlacement {
532
+ anchor: string;
533
+ occurrence: number;
534
+ sectionIndex: number;
535
+ mode: "overlap" | "right";
536
+ posXMm: number;
537
+ posYMm: number;
538
+ sizeMm: number;
539
+ /** ZIP에 추가된 이미지 파트 경로 (BinData/imageN.ext) */
540
+ entry: string;
541
+ }
542
+ interface PlaceSealResult {
543
+ buffer: ArrayBuffer;
544
+ placed: SealPlacement[];
545
+ }
546
+ /**
547
+ * HWPX에 도장/서명 이미지를 앵커 문구 기준으로 부유 배치한다.
548
+ *
549
+ * @param hwpxBuffer 원본 HWPX
550
+ * @param ops 도장 배치 요청 (여러 개 가능 — 같은 이미지 재사용 시에도 op마다 파트가 추가됨)
551
+ * @throws KordocError 앵커 미발견 (본문 내 등장 횟수를 메시지에 포함)
552
+ */
553
+ declare function placeSealHwpx(hwpxBuffer: ArrayBuffer, ops: SealOp[]): Promise<PlaceSealResult>;
459
554
 
460
555
  /**
461
556
  * 공문서(公文書) 모드 — 한국 행정 공문서 표준 서식 렌더링 로직
@@ -802,6 +897,33 @@ declare function patchHwpx(original: Uint8Array, editedMarkdown: string, options
802
897
  */
803
898
  declare function patchHwp(original: Uint8Array, editedMarkdown: string, options?: PatchOptions): Promise<PatchResult>;
804
899
 
900
+ /**
901
+ * HWPX 구조 검증 — 한컴오피스/한컴독스가 열기를 거부하는 컨테이너 결함을 사전에 잡는다.
902
+ *
903
+ * 검사 항목 (claw-hwp validate.py의 실측 검사셋 이식 — MIT © DoHyun468/claw-hwp):
904
+ * - 유효한 ZIP인지, mimetype이 첫 엔트리이고 내용이 application/hwp+zip인지
905
+ * - 필수 파일 존재 (META-INF/container.xml, content.hpf, header.xml, section0.xml)
906
+ * - XML/HPF/RDF 엔트리 웰폼드
907
+ * - header.xml secCnt == 실제 Contents/sectionN.xml 수
908
+ * (한컴독스는 실제 파일 목록이 아니라 secCnt를 신뢰하고, 불일치 시 열기를 거부한다)
909
+ * - content.hpf manifest의 <opf:item href>가 전부 실존하는지
910
+ */
911
+ /** 검증에서 발견된 문제 하나 */
912
+ interface ValidateIssue {
913
+ /** 문제가 발견된 zip 내부 경로 (컨테이너 전역 문제면 생략) */
914
+ path?: string;
915
+ message: string;
916
+ }
917
+ /** validateHwpx 결과 */
918
+ interface ValidateResult {
919
+ ok: boolean;
920
+ issues: ValidateIssue[];
921
+ /** 검사한 zip 엔트리 수 (디렉토리 제외) */
922
+ entryCount: number;
923
+ }
924
+ /** HWPX 버퍼의 컨테이너 구조를 검증한다. 문제가 없으면 ok=true. */
925
+ declare function validateHwpx(buffer: ArrayBuffer | Uint8Array): Promise<ValidateResult>;
926
+
805
927
  /**
806
928
  * HWPX 문서 세션 — 에디터 통합용 블록 단위 증분 패치 API (v3.1).
807
929
  *
@@ -955,17 +1077,33 @@ declare function blocksToPdf(blocks: IRBlock[], options?: PrintOptions): Promise
955
1077
  * - 좌표 속성엔 uint32로 저장된 음수가 섞여 있다(toInt32 필수).
956
1078
  * - 표 열은 span 제약 경계 전파로, 행은 rs=1 max + 콘텐츠 초과 성장으로 푼다.
957
1079
  *
958
- * 범위: 1페이지(section0) 한정, 수식·그리기개체 도형은 미지원(경고 수집).
1080
+ * 페이지: 최상위 lineseg vertpos는 페이지 로컬(페이지마다 0부터 리셋)이므로 역행
1081
+ * 지점을 페이지 경계로 감지, 전 페이지를 세로 스택으로 그린다(페이지별 흰 배경 +
1082
+ * 클립). 페이지에 걸친 표는 시작 페이지에서 잘린다(조판 캐시에 분할점이 없음).
1083
+ *
1084
+ * 범위: section0 한정(다중 구역은 첫 구역만), 수식·그리기개체 도형은 미지원(경고 수집).
959
1085
  */
1086
+
960
1087
  interface RenderSvgOptions {
961
1088
  /** 이미지 1장당 허용 최대 바이트 (기본 40MB) */
962
1089
  maxImageBytes?: number;
1090
+ /** 검색어 형광펜 — 텍스트 조각 내 매치 구간에 배경 rect (대소문자 무시).
1091
+ * charPr(스타일) 경계에 걸친 매치는 칠하지 못한다. */
1092
+ highlights?: string[];
1093
+ /** Tier-2 reflow — 조판 캐시(linesegarray) 없는 파일도 순수 TS 조판으로 렌더.
1094
+ * 캐시가 있으면 무시(한컴본은 캐시 재생). 기본 false(캐시 없으면 KordocError). */
1095
+ reflow?: boolean;
1096
+ /** reflow 줄바꿈 모드 — 'keep'(어절, Windows 한글·공문서) / 'charAll'(글자, macOS·전자결재) */
1097
+ reflowMode?: WrapMode;
963
1098
  }
964
1099
  interface RenderSvgResult {
965
1100
  svg: string;
966
- /** 페이지 크기 (pt) */
1101
+ /** 페이지 (pt) */
967
1102
  width: number;
1103
+ /** 전체 캔버스 높이 (pt) — 페이지 세로 스택 + 간격 */
968
1104
  height: number;
1105
+ /** 렌더된 페이지 수 */
1106
+ pageCount: number;
969
1107
  warnings: string[];
970
1108
  stats: {
971
1109
  texts: number;
@@ -1077,6 +1215,6 @@ interface FillFormOutput {
1077
1215
  * console.log(result.output) // 채워진 마크다운
1078
1216
  * ```
1079
1217
  */
1080
- declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillValue>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1218
+ declare function fillForm(input: string | ArrayBuffer | Buffer, values: Record<string, FillInput>, outputFormat?: FillOutputFormat): Promise<FillFormOutput>;
1081
1219
 
1082
- export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, type DiffChangeType, type DiffResult, type DocumentMetadata, type DocumentQualitySummary, type ErrorCode, type ExtractedImage, type FileType, type FillFormOutput, type FillOutputFormat, type FillResult, type FillValue, type FormField, type FormFieldSchema, type FormFieldType, type FormResult, type FormSchemaResult, type GongmunFont, 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 PrintOptions, type PrintPreset, type RenderSvgOptions, type RenderSvgResult, SPACE_EM_FIXED, SPACE_EM_FONT, type ScanCell, type ScanParaKind, type ScanParagraph, type ScanTable, type SectionScan, type SpliceEdit, type TRange, VERSION, 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, fitRatioForFewerLines, inferFieldType, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, measureTextWidth, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord };
1220
+ export { type BlockCapability, type BlockCapabilityInfo, type BlockDiff, type BlockEdit, type BlockSourceRef, type BoundingBox, type CellCapability, type CellContext, type CellDiff, 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 GongmunFont, 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, 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, inferFieldType, isHwpxFile, isLabelCell, isOldHwpFile, isPdfFile, isZipFile, markdownToHwpx, markdownToPdf, measureTextWidth, normalizeGongmunPreset, openHwpxDocument, parse, parseDocx, parseHwp, parseHwp3, parseHwpml, parseHwpx, parsePdf, parseXls, parseXlsx, patchHwp, patchHwpx, patchHwpxBlocks, placeSealHwpx, renderHtml, renderHwpxToSvg, scanSectionXml, simulateWrap, simulateWrapKeepWord, validateHwpx };