kordoc 4.24.13 → 4.24.15

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 (127) hide show
  1. package/README.md +7 -7
  2. package/dist/{-NBCZTPBD.js → -CCZTES5C.js} +11 -11
  3. package/dist/{chunk-XWWQGSEP.js → chunk-4EVUCAW5.js} +2 -2
  4. package/dist/{chunk-VPKZB6Y7.cjs → chunk-4ZNM7XRW.cjs} +6 -6
  5. package/dist/{chunk-VPKZB6Y7.cjs.map → chunk-4ZNM7XRW.cjs.map} +1 -1
  6. package/dist/{chunk-XGESPSWE.cjs → chunk-6KQWC2KN.cjs} +3 -3
  7. package/dist/{chunk-XGESPSWE.cjs.map → chunk-6KQWC2KN.cjs.map} +1 -1
  8. package/dist/{chunk-QW2H2HHS.js → chunk-6WEHXC2D.js} +315 -6
  9. package/dist/chunk-6WEHXC2D.js.map +1 -0
  10. package/dist/{chunk-PUHBCAXI.js → chunk-7Y4MVNYA.js} +11 -11
  11. package/dist/{chunk-CKOCIQU6.js → chunk-7YCKDE5X.js} +2 -2
  12. package/dist/{chunk-FJ3IKKDV.js → chunk-DULJ7PPP.js} +315 -6
  13. package/dist/chunk-DULJ7PPP.js.map +1 -0
  14. package/dist/{chunk-KTXDK5A6.js → chunk-E5H5WHJH.js} +2 -2
  15. package/dist/{chunk-A232MW5F.js → chunk-EY3PT2X7.js} +2 -2
  16. package/dist/{chunk-W52B6GOE.cjs → chunk-GDE4YE2P.cjs} +3 -3
  17. package/dist/{chunk-W52B6GOE.cjs.map → chunk-GDE4YE2P.cjs.map} +1 -1
  18. package/dist/{chunk-UVQOPGOA.js → chunk-GZ3BY2LV.js} +14 -9
  19. package/dist/chunk-GZ3BY2LV.js.map +1 -0
  20. package/dist/{chunk-ZUMOEVMV.js → chunk-HZFYPOBJ.js} +3 -3
  21. package/dist/{chunk-OVQWOOS3.js → chunk-IGLRJCO6.js} +2 -2
  22. package/dist/{chunk-A4CYMI55.js → chunk-K37LMDT5.js} +2 -2
  23. package/dist/{chunk-X2E5QCKO.js → chunk-KMSLXG5F.js} +2 -2
  24. package/dist/{chunk-DMPX4KLC.js → chunk-KOHEEPQV.js} +2 -2
  25. package/dist/{chunk-37MTSMUF.js → chunk-MTAQVHCB.js} +2 -2
  26. package/dist/{chunk-2H2VYPM2.cjs → chunk-OICA67AT.cjs} +2 -2
  27. package/dist/{chunk-2H2VYPM2.cjs.map → chunk-OICA67AT.cjs.map} +1 -1
  28. package/dist/{chunk-QAGPSWGH.js → chunk-PCHGHLUP.js} +2 -2
  29. package/dist/{chunk-BC4LVU4D.js → chunk-SLHWOJNZ.js} +2 -2
  30. package/dist/{chunk-ZSCDH3NU.js → chunk-T7MDUY5X.js} +2 -2
  31. package/dist/{chunk-QVEAR6IR.js → chunk-UGO3UFXX.js} +48 -7
  32. package/dist/chunk-UGO3UFXX.js.map +1 -0
  33. package/dist/{chunk-WAWREGAC.js → chunk-UV2ZS65C.js} +2 -2
  34. package/dist/{chunk-4I2CKMKU.js → chunk-VNB2IKVA.js} +3 -3
  35. package/dist/{chunk-IQGXY63Y.js → chunk-VSYLST4K.js} +49 -8
  36. package/dist/chunk-VSYLST4K.js.map +1 -0
  37. package/dist/{chunk-QZ2H4ZTO.cjs → chunk-X2XZXDBZ.cjs} +390 -81
  38. package/dist/chunk-X2XZXDBZ.cjs.map +1 -0
  39. package/dist/{chunk-WOVJRXIA.js → chunk-XW7L76FE.js} +2 -2
  40. package/dist/{chunk-BJBPBU5B.js → chunk-Y3VNNGB2.js} +2 -2
  41. package/dist/{chunk-U2VAABMK.cjs → chunk-YAK4U7CC.cjs} +194 -153
  42. package/dist/chunk-YAK4U7CC.cjs.map +1 -0
  43. package/dist/chunks-74SE5QB2.js +10 -0
  44. package/dist/cli.js +30 -30
  45. package/dist/{formula-WFL6JRCR.js → formula-54IFKOYU.js} +3 -3
  46. package/dist/{formula-M4FM364X.js → formula-EW7XLBSA.js} +4 -4
  47. package/dist/{formula-ZKZGV6JV.cjs → formula-Q4MFVPEO.cjs} +9 -9
  48. package/dist/{formula-ZKZGV6JV.cjs.map → formula-Q4MFVPEO.cjs.map} +1 -1
  49. package/dist/{image-ocr-47CBNIS5.js → image-ocr-GWF2XELH.js} +9 -9
  50. package/dist/{image-ocr-YJISJPKE.js → image-ocr-I7UGQZF5.js} +6 -6
  51. package/dist/{image-ocr-2V3M3ZEA.cjs → image-ocr-OGJ6A3ML.cjs} +17 -17
  52. package/dist/{image-ocr-2V3M3ZEA.cjs.map → image-ocr-OGJ6A3ML.cjs.map} +1 -1
  53. package/dist/index.cjs +368 -363
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.js +14 -9
  56. package/dist/index.js.map +1 -1
  57. package/dist/mcp.js +23 -23
  58. package/dist/{model-bundle-7W344HDI.js → model-bundle-43YHGZCC.js} +5 -5
  59. package/dist/{models-TBHMNI7M.js → models-O3NS6OPX.js} +5 -5
  60. package/dist/{parse-worker-v2-JUYUEXCY.js → parse-worker-v2-OXW3CQOW.js} +12 -12
  61. package/dist/{parser-RNJ4KSDF.js → parser-B3RVTCOY.js} +9 -9
  62. package/dist/{parser-R44KTBZX.cjs → parser-FMVOWRG4.cjs} +159 -159
  63. package/dist/{parser-R44KTBZX.cjs.map → parser-FMVOWRG4.cjs.map} +1 -1
  64. package/dist/{parser-EKQCZLML.js → parser-H6OY6UWW.js} +12 -12
  65. package/dist/pdf-ocr-5Z6GDYBQ.cjs +35 -0
  66. package/dist/{pdf-ocr-74BOCXAT.cjs.map → pdf-ocr-5Z6GDYBQ.cjs.map} +1 -1
  67. package/dist/{pdf-ocr-ZAF4P74R.js → pdf-ocr-NE6Y4I6O.js} +6 -6
  68. package/dist/{pdf-ocr-EE5KGFVX.js → pdf-ocr-QHW74LO6.js} +9 -9
  69. package/dist/{profile-io-RU3RVIYV.js → profile-io-2IOYOBGP.js} +3 -3
  70. package/dist/{rasterize-UNCPM26D.js → rasterize-ZLPDGEZY.js} +3 -3
  71. package/dist/{redact-doc-BFE4UZCY.js → redact-doc-CDFM5S7S.js} +11 -11
  72. package/dist/{render-3DXTLKIA.js → render-VXAEYSJA.js} +7 -7
  73. package/dist/seal-YSBFBEXC.js +10 -0
  74. package/dist/{setup-7POQAKDG.js → setup-CBWVQJID.js} +3 -3
  75. package/dist/visual-MJVIFZHH.js +21 -0
  76. package/dist/{watch-37YCXJWW.js → watch-2SA3CTRT.js} +12 -12
  77. package/package.json +1 -1
  78. package/dist/chunk-FJ3IKKDV.js.map +0 -1
  79. package/dist/chunk-IQGXY63Y.js.map +0 -1
  80. package/dist/chunk-QVEAR6IR.js.map +0 -1
  81. package/dist/chunk-QW2H2HHS.js.map +0 -1
  82. package/dist/chunk-QZ2H4ZTO.cjs.map +0 -1
  83. package/dist/chunk-U2VAABMK.cjs.map +0 -1
  84. package/dist/chunk-UVQOPGOA.js.map +0 -1
  85. package/dist/chunks-IXFBIZPW.js +0 -10
  86. package/dist/pdf-ocr-74BOCXAT.cjs +0 -35
  87. package/dist/seal-3LBTETDG.js +0 -10
  88. package/dist/visual-7SVIGIJC.js +0 -21
  89. /package/dist/{-NBCZTPBD.js.map → -CCZTES5C.js.map} +0 -0
  90. /package/dist/{chunk-XWWQGSEP.js.map → chunk-4EVUCAW5.js.map} +0 -0
  91. /package/dist/{chunk-PUHBCAXI.js.map → chunk-7Y4MVNYA.js.map} +0 -0
  92. /package/dist/{chunk-CKOCIQU6.js.map → chunk-7YCKDE5X.js.map} +0 -0
  93. /package/dist/{chunk-KTXDK5A6.js.map → chunk-E5H5WHJH.js.map} +0 -0
  94. /package/dist/{chunk-A232MW5F.js.map → chunk-EY3PT2X7.js.map} +0 -0
  95. /package/dist/{chunk-ZUMOEVMV.js.map → chunk-HZFYPOBJ.js.map} +0 -0
  96. /package/dist/{chunk-OVQWOOS3.js.map → chunk-IGLRJCO6.js.map} +0 -0
  97. /package/dist/{chunk-A4CYMI55.js.map → chunk-K37LMDT5.js.map} +0 -0
  98. /package/dist/{chunk-X2E5QCKO.js.map → chunk-KMSLXG5F.js.map} +0 -0
  99. /package/dist/{chunk-DMPX4KLC.js.map → chunk-KOHEEPQV.js.map} +0 -0
  100. /package/dist/{chunk-37MTSMUF.js.map → chunk-MTAQVHCB.js.map} +0 -0
  101. /package/dist/{chunk-QAGPSWGH.js.map → chunk-PCHGHLUP.js.map} +0 -0
  102. /package/dist/{chunk-BC4LVU4D.js.map → chunk-SLHWOJNZ.js.map} +0 -0
  103. /package/dist/{chunk-ZSCDH3NU.js.map → chunk-T7MDUY5X.js.map} +0 -0
  104. /package/dist/{chunk-WAWREGAC.js.map → chunk-UV2ZS65C.js.map} +0 -0
  105. /package/dist/{chunk-4I2CKMKU.js.map → chunk-VNB2IKVA.js.map} +0 -0
  106. /package/dist/{chunk-WOVJRXIA.js.map → chunk-XW7L76FE.js.map} +0 -0
  107. /package/dist/{chunk-BJBPBU5B.js.map → chunk-Y3VNNGB2.js.map} +0 -0
  108. /package/dist/{chunks-IXFBIZPW.js.map → chunks-74SE5QB2.js.map} +0 -0
  109. /package/dist/{formula-WFL6JRCR.js.map → formula-54IFKOYU.js.map} +0 -0
  110. /package/dist/{formula-M4FM364X.js.map → formula-EW7XLBSA.js.map} +0 -0
  111. /package/dist/{image-ocr-47CBNIS5.js.map → image-ocr-GWF2XELH.js.map} +0 -0
  112. /package/dist/{image-ocr-YJISJPKE.js.map → image-ocr-I7UGQZF5.js.map} +0 -0
  113. /package/dist/{model-bundle-7W344HDI.js.map → model-bundle-43YHGZCC.js.map} +0 -0
  114. /package/dist/{models-TBHMNI7M.js.map → models-O3NS6OPX.js.map} +0 -0
  115. /package/dist/{parse-worker-v2-JUYUEXCY.js.map → parse-worker-v2-OXW3CQOW.js.map} +0 -0
  116. /package/dist/{parser-RNJ4KSDF.js.map → parser-B3RVTCOY.js.map} +0 -0
  117. /package/dist/{parser-EKQCZLML.js.map → parser-H6OY6UWW.js.map} +0 -0
  118. /package/dist/{pdf-ocr-EE5KGFVX.js.map → pdf-ocr-NE6Y4I6O.js.map} +0 -0
  119. /package/dist/{pdf-ocr-ZAF4P74R.js.map → pdf-ocr-QHW74LO6.js.map} +0 -0
  120. /package/dist/{profile-io-RU3RVIYV.js.map → profile-io-2IOYOBGP.js.map} +0 -0
  121. /package/dist/{rasterize-UNCPM26D.js.map → rasterize-ZLPDGEZY.js.map} +0 -0
  122. /package/dist/{redact-doc-BFE4UZCY.js.map → redact-doc-CDFM5S7S.js.map} +0 -0
  123. /package/dist/{render-3DXTLKIA.js.map → render-VXAEYSJA.js.map} +0 -0
  124. /package/dist/{seal-3LBTETDG.js.map → seal-YSBFBEXC.js.map} +0 -0
  125. /package/dist/{setup-7POQAKDG.js.map → setup-CBWVQJID.js.map} +0 -0
  126. /package/dist/{visual-7SVIGIJC.js.map → visual-MJVIFZHH.js.map} +0 -0
  127. /package/dist/{watch-37YCXJWW.js.map → watch-2SA3CTRT.js.map} +0 -0
@@ -51,10 +51,10 @@ import {
51
51
  resolveParaHeading,
52
52
  simulateWrap,
53
53
  takeTocLeaders
54
- } from "./chunk-UVQOPGOA.js";
54
+ } from "./chunk-GZ3BY2LV.js";
55
55
  import {
56
56
  blocksToPages
57
- } from "./chunk-37MTSMUF.js";
57
+ } from "./chunk-MTAQVHCB.js";
58
58
  import {
59
59
  bmpToPng,
60
60
  inlineImagesIntoMarkdown
@@ -76,7 +76,7 @@ import {
76
76
  tidyScriptTags,
77
77
  unframeLayoutTables,
78
78
  wrapScript
79
- } from "./chunk-CKOCIQU6.js";
79
+ } from "./chunk-7YCKDE5X.js";
80
80
  import {
81
81
  MAX_COLS,
82
82
  MAX_ROWS,
@@ -100,7 +100,7 @@ import {
100
100
  noteTableHtml,
101
101
  sanitizeText,
102
102
  visibleText
103
- } from "./chunk-DMPX4KLC.js";
103
+ } from "./chunk-KOHEEPQV.js";
104
104
  import {
105
105
  ANNOTATION_BLANK_RE,
106
106
  ValueCursor,
@@ -133,7 +133,7 @@ import {
133
133
  resolveUnmatched,
134
134
  scanInlineSegments,
135
135
  scanSectionXml
136
- } from "./chunk-ZUMOEVMV.js";
136
+ } from "./chunk-HZFYPOBJ.js";
137
137
  import {
138
138
  MAX_DECOMPRESS_SIZE,
139
139
  MAX_XML_DEPTH,
@@ -150,7 +150,7 @@ import {
150
150
  localName,
151
151
  rawTextContent,
152
152
  readZipEntry
153
- } from "./chunk-XWWQGSEP.js";
153
+ } from "./chunk-4EVUCAW5.js";
154
154
  import {
155
155
  KordocError,
156
156
  VERSION,
@@ -167,7 +167,7 @@ import {
167
167
  toArrayBuffer,
168
168
  unescapeHtml,
169
169
  unzipLimitBytes
170
- } from "./chunk-WAWREGAC.js";
170
+ } from "./chunk-UV2ZS65C.js";
171
171
 
172
172
  // src/table/visual.ts
173
173
  import { readFile as readFile2 } from "fs/promises";
@@ -19351,7 +19351,7 @@ var MIN_SIDE = 24;
19351
19351
  async function ocrEmbeddedImages(blocks, options, warnings) {
19352
19352
  const ocr = options?.ocr;
19353
19353
  if (ocr !== true && ocr !== "force" && typeof ocr !== "function") return false;
19354
- const { parseImageDocument } = await import("./image-ocr-47CBNIS5.js");
19354
+ const { parseImageDocument } = await import("./image-ocr-GWF2XELH.js");
19355
19355
  let inserted = false, unreadable = 0;
19356
19356
  let failed = null;
19357
19357
  const walk = async (list, depth) => {
@@ -34072,7 +34072,7 @@ function scriptsOff(r, off) {
34072
34072
  }
34073
34073
  async function parseImage(buffer, options) {
34074
34074
  try {
34075
- const { parseImageDocument } = await import("./image-ocr-47CBNIS5.js");
34075
+ const { parseImageDocument } = await import("./image-ocr-GWF2XELH.js");
34076
34076
  const { blocks, warnings, lines } = await parseImageDocument(buffer, options);
34077
34077
  stripScriptTags({ blocks });
34078
34078
  return {
@@ -34136,7 +34136,7 @@ async function parseHwp(buffer, options) {
34136
34136
  async function parsePdf(buffer, options) {
34137
34137
  let parsePdfDocument;
34138
34138
  try {
34139
- const mod = await import("./parser-EKQCZLML.js");
34139
+ const mod = await import("./parser-H6OY6UWW.js");
34140
34140
  parsePdfDocument = mod.parsePdfDocument;
34141
34141
  } catch {
34142
34142
  return {
@@ -34375,4 +34375,4 @@ export {
34375
34375
  parseHwpml,
34376
34376
  fillForm
34377
34377
  };
34378
- //# sourceMappingURL=chunk-PUHBCAXI.js.map
34378
+ //# sourceMappingURL=chunk-7Y4MVNYA.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  visibleText
4
- } from "./chunk-DMPX4KLC.js";
4
+ } from "./chunk-KOHEEPQV.js";
5
5
 
6
6
  // src/script-tags.ts
7
7
  var LITERAL_TAG = /<(?=\/?(?:u|sup|sub)>)/g;
@@ -336,4 +336,4 @@ export {
336
336
  HEADING_RATIO_H2,
337
337
  HEADING_RATIO_H3
338
338
  };
339
- //# sourceMappingURL=chunk-CKOCIQU6.js.map
339
+ //# sourceMappingURL=chunk-7YCKDE5X.js.map
@@ -35,14 +35,14 @@ import {
35
35
  splitRowBands,
36
36
  starRun,
37
37
  tallInkCount
38
- } from "./chunk-IQGXY63Y.js";
38
+ } from "./chunk-VSYLST4K.js";
39
39
  import {
40
40
  validateOcrOptions
41
- } from "./chunk-BJBPBU5B.js";
41
+ } from "./chunk-Y3VNNGB2.js";
42
42
  import {
43
43
  KordocError,
44
44
  OPTIONAL_DEP_INSTALL_HINT
45
- } from "./chunk-OVQWOOS3.js";
45
+ } from "./chunk-IGLRJCO6.js";
46
46
 
47
47
  // src/ocr/ruling-lines.ts
48
48
  var INK_LUMA_MAX = 205;
@@ -392,6 +392,7 @@ function restoreGlyphs(rgba, pageW, box, text, steps, stepPx, note = {}) {
392
392
  const gray = grayCrop(rgba, pageW, box);
393
393
  const c = { chars, cx: (i) => (steps[i] + 0.5) * stepPx, gray, w: box.w, h: box.h, ink: inkStats(gray) };
394
394
  if (/[[\]]/.test(text)) brackets(c);
395
+ if (text.includes("'")) cornerQuotes(c);
395
396
  if (/['"]/.test(text)) quotes(c);
396
397
  if (/(^|\D)[1-9](\D|$)/.test(text)) circled(c);
397
398
  if (text.includes("*")) stars(c);
@@ -445,6 +446,19 @@ function cornerCommas({ chars, cx, gray, w, h, ink }) {
445
446
  }
446
447
  }
447
448
  }
449
+ function cornerQuotes({ chars, cx, gray, w, h, ink }) {
450
+ for (let i = 0; i < chars.length; i++) {
451
+ if (chars[i] !== "'" || !/^[가-힣]/.test(chars[i + 1] ?? "")) continue;
452
+ const f = bracketFeatures(gray, w, h, ink, cx(i));
453
+ if (!f || f.ch < f.charH * 0.45 || bracketShape(f, false) !== "\u300C") continue;
454
+ const rest = chars.slice(i + 1), end = rest.findIndex((c) => c === "'" || c === "\u300D" || c === ",");
455
+ const pair = end >= 0 && rest[end] !== "'" && (rest[end] === "\u300D" || (() => {
456
+ const g = bracketFeatures(gray, w, h, ink, cx(i + 1 + end));
457
+ return !!g && bracketShape(g, true) === "\u300D";
458
+ })());
459
+ if (pair) chars[i] = "\u300C";
460
+ }
461
+ }
448
462
  function brackets({ chars, cx, gray, w, h, ink }) {
449
463
  for (let i = 0; i < chars.length; i++) {
450
464
  if (chars[i] !== "[" && chars[i] !== "]") continue;
@@ -530,6 +544,7 @@ function gaps({ chars, cx, gray, w, h, ink }) {
530
544
  }
531
545
  if (cover.length) {
532
546
  if (g.mark.startsWith("\u25A1") && cover.length === 1 && /^[0Oo\u25cb]$/.test(chars[cover[0]])) chars[cover[0]] = "\u25A1";
547
+ if (g.mark === "\u3002" && cover.length === 1 && /^[\u00b7\u2022\u318d]$/.test(chars[cover[0]])) chars[cover[0]] = "\u3002";
533
548
  continue;
534
549
  }
535
550
  if (g.mark === "\u25A1\0") continue;
@@ -546,6 +561,14 @@ function gaps({ chars, cx, gray, w, h, ink }) {
546
561
  if (loose.some((o) => o !== g && Math.abs((o.x0 + o.x1) / 2 - mid) <= pitch * 1.5)) continue;
547
562
  if (/[\u2026.\u00b7]$/.test(prev) || /^[\u2026.\u00b7]/.test(next)) continue;
548
563
  }
564
+ if (g.mark === "\u300C") {
565
+ let sp = chars.findIndex((c, i) => c === " " && near(i));
566
+ if (sp >= 0) while (chars[sp + 1] === " ") sp++;
567
+ if (sp >= 0) {
568
+ chars[sp] = g.mark;
569
+ continue;
570
+ }
571
+ }
549
572
  if (g.mark === "\xB7") {
550
573
  if (/^\d/.test(next)) continue;
551
574
  const sp = chars.findIndex((c, i) => c === " " && near(i));
@@ -559,10 +582,23 @@ function gaps({ chars, cx, gray, w, h, ink }) {
559
582
  }
560
583
  function ring({ chars, cx, gray, w, h, ink }) {
561
584
  const k = chars.findIndex((c) => c.trim());
562
- if (k < 0 || !/^[\u3147Oo0\u25cb]$/.test(chars[k])) return false;
585
+ if (k < 0 || !/^[\u3147Oo0\u25cbCc]$/.test(chars[k])) return false;
563
586
  const rest = chars.slice(k + 1).join("").trimStart();
587
+ const live = chars.map((c, i) => i).filter((i) => chars[i].trim());
588
+ if (live.length <= 3 && live.every((i) => /^[Oo]$/.test(chars[i]))) {
589
+ if (leadingBullet(gray, w, h, ink, cx(live[0]))?.mark === "\u25CE") return false;
590
+ if (!live.every((i) => ringBullet(gray, w, h, ink, cx(i)) === "\u25CB")) return false;
591
+ for (const i of live) chars[i] = "\u25CB";
592
+ return true;
593
+ }
594
+ if (/^[A-Z]{2,}/.test(rest) && /^[Oo0]$/.test(chars[k])) {
595
+ if (ringBullet(gray, w, h, ink, cx(k)) !== "\u25CB") return false;
596
+ chars[k] = chars[k + 1] === " " ? "\u25CB" : "\u25CB ";
597
+ return true;
598
+ }
564
599
  if (!/^[(\[「【<]?\d*[가-힣]/.test(rest)) return false;
565
600
  const r = ringBullet(gray, w, h, ink, cx(k));
601
+ if (/^[Cc]$/.test(chars[k]) && r !== "\u25CB") return false;
566
602
  if (r) chars[k] = r;
567
603
  return r !== null;
568
604
  }
@@ -622,6 +658,7 @@ function restoreSymbols(text, ringDecided = false) {
622
658
  s = s.replace(/[\u2206\u0394]/g, "\u25B3");
623
659
  s = s.replace(/\(cid:\d*\)/g, "");
624
660
  s = s.replace(/(^|[^\uac00-\ud7a3])(전|현)\(\s?\)(?=\S)/g, (_, a, b) => `${a}${b}(${b === "\uC804" ? "\u524D" : "\u73FE"})`);
661
+ if (/[가-힣]/.test(s)) s = s.replace(/(\d)l(?![A-Za-z])/g, "$1\u2113");
625
662
  s = s.replace(/([((])\s?[A-Za-z@&]\s?(?=(?:0\d{1,2}-)?\d{3,4}-\d{4}\b)/g, "$1\u260E");
626
663
  return smartQuotes(dateDots(dateCommas(joinDigitGroups(s))));
627
664
  }
@@ -869,6 +906,247 @@ var MIN_INK_RATIO = 0.01;
869
906
  var MAX_LOCAL_MODEL_BYTES = 1024 * 1024 * 1024;
870
907
  var DET_MEAN = [0.485, 0.456, 0.406];
871
908
  var DET_STD = [0.229, 0.224, 0.225];
909
+ function rowHeadDashes(rgba, width, items) {
910
+ const out = [];
911
+ const dark = (x, y) => {
912
+ const p = (y * width + x) * 4;
913
+ return rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 < 160;
914
+ };
915
+ const inBox = (x, y) => items.some((b) => x >= b.x && x < b.x + b.w && y >= b.y && y < b.y + b.h);
916
+ const done = /* @__PURE__ */ new Set();
917
+ for (const it of [...items]) {
918
+ if (done.has(it) || it.h < 12) continue;
919
+ const row = items.filter((o) => Math.min(o.y + o.h, it.y + it.h) - Math.max(o.y, it.y) >= Math.min(o.h, it.h) * 0.6);
920
+ for (const o of row) done.add(o);
921
+ if (row.reduce((k, o) => k + (o.text.match(/[가-힣]/g)?.length ?? 0), 0) < 2) continue;
922
+ const first = row.reduce((m, o) => o.x < m.x ? o : m);
923
+ if (!/^[가-힣]/.test(first.text)) continue;
924
+ if (row.filter((o) => /\d/.test(o.text)).length >= 2) continue;
925
+ const y0 = Math.min(...row.map((o) => o.y)), y1 = Math.max(...row.map((o) => o.y + o.h)), h = y1 - y0;
926
+ const x0 = Math.max(0, Math.round(first.x - 2.5 * h)), x1 = first.x - 2;
927
+ let minX = -1, maxX = -1, minY = Infinity, maxY = -1, groups = 0;
928
+ for (let x = x0; x < x1; x++) {
929
+ let on = false;
930
+ for (let y = y0; y < y1; y++) if (dark(x, y) && !inBox(x, y)) {
931
+ on = true;
932
+ if (y < minY) minY = y;
933
+ if (y > maxY) maxY = y;
934
+ }
935
+ if (!on) continue;
936
+ if (maxX < 0 || x - maxX > 2) {
937
+ groups++;
938
+ if (groups === 1) minX = x;
939
+ }
940
+ maxX = x;
941
+ }
942
+ const bw = maxX - minX + 1, bh = maxY - minY + 1, cy = ((minY + maxY) / 2 - y0) / h;
943
+ if (groups !== 1 || bh > h * 0.2 || bw < h * 0.3 || bw > h * 1.2 || cy < 0.3 || cy > 0.7) continue;
944
+ const faint = (x, y) => {
945
+ const p = (y * width + x) * 4;
946
+ return rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 < 230;
947
+ };
948
+ let touch = minX <= x0;
949
+ for (let y = minY; y <= maxY && !touch; y++) for (let d = 2; d <= 4 && !touch; d++) touch = minX - d >= 0 && faint(minX - d, y) || faint(maxX + d, y);
950
+ if (touch) continue;
951
+ out.push({ text: "-", x: minX, y: y0, w: bw, h, confidence: first.confidence });
952
+ }
953
+ return out;
954
+ }
955
+ function rowTailBoxes(rgba, width, items) {
956
+ const out = [];
957
+ const dark = (x, y) => {
958
+ const p = (y * width + x) * 4;
959
+ return rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 < 160;
960
+ };
961
+ const done = /* @__PURE__ */ new Set();
962
+ for (const it of items) {
963
+ if (done.has(it) || it.h < 12) continue;
964
+ const row = items.filter((o) => Math.min(o.y + o.h, it.y + it.h) - Math.max(o.y, it.y) >= Math.min(o.h, it.h) * 0.6);
965
+ for (const o of row) done.add(o);
966
+ if (row.reduce((k, o) => k + (o.text.match(/[가-힣]/g)?.length ?? 0), 0) < 2) continue;
967
+ const last = row.reduce((m, o) => o.x + o.w > m.x + m.w ? o : m);
968
+ if (/\d$/.test(last.text.trim())) continue;
969
+ const y0 = Math.min(...row.map((o) => o.y)), y1 = Math.max(...row.map((o) => o.y + o.h)), h = y1 - y0;
970
+ const x0 = last.x + last.w + 4, x1 = Math.floor(width * 0.95);
971
+ if (x1 - x0 < h) continue;
972
+ let groups = 0, minX = -1, maxX = -1, minY = Infinity, maxY = -1;
973
+ for (let x = x0; x < x1; x++) {
974
+ let on = false;
975
+ for (let y = y0; y < y1; y++) if (dark(x, y)) {
976
+ on = true;
977
+ if (y < minY) minY = y;
978
+ if (y > maxY) maxY = y;
979
+ }
980
+ if (!on) continue;
981
+ if (maxX < 0 || x - maxX > h) {
982
+ groups++;
983
+ if (groups === 1) minX = x;
984
+ }
985
+ maxX = x;
986
+ }
987
+ if (groups !== 1 || maxY - minY + 1 < h * 0.5 || maxX - minX + 1 > h * 4) continue;
988
+ const height = Math.floor(rgba.length / 4 / width);
989
+ let rule = false;
990
+ for (let x = minX; x <= maxX && !rule; x++) rule = minY > 1 && dark(x, minY - 2) || maxY + 2 < height && dark(x, maxY + 2);
991
+ if (rule) continue;
992
+ const pad = 4;
993
+ out.push({ x: Math.max(0, minX - pad), y: Math.max(0, minY - pad), w: maxX - minX + 1 + 2 * pad, h: maxY - minY + 1 + 2 * pad });
994
+ }
995
+ return out;
996
+ }
997
+ function placeholderSquares(rgba, width, height, items) {
998
+ const dark = new Uint8Array(width * height);
999
+ for (let p = 0, i = 0; p < dark.length; p++, i += 4) dark[p] = rgba[i] * 77 + rgba[i + 1] * 150 + rgba[i + 2] * 29 >> 8 < 128 ? 1 : 0;
1000
+ const covered = (x, y) => items.some((b) => x >= b.x - 2 && x < b.x + b.w + 2 && y >= b.y - 2 && y < b.y + b.h + 2);
1001
+ const seen = new Uint8Array(width * height);
1002
+ const squares = [], bars = [];
1003
+ const stack = [];
1004
+ for (let start = 0; start < dark.length; start++) {
1005
+ if (!dark[start] || seen[start]) continue;
1006
+ const c = { x0: width, y0: height, x1: -1, y1: -1, n: 0, px: [] };
1007
+ stack.push(start);
1008
+ seen[start] = 1;
1009
+ while (stack.length) {
1010
+ const p = stack.pop(), x = p % width, y = (p - x) / width;
1011
+ c.n++;
1012
+ if (c.px.length < 4e3) c.px.push(p);
1013
+ if (x < c.x0) c.x0 = x;
1014
+ if (x > c.x1) c.x1 = x;
1015
+ if (y < c.y0) c.y0 = y;
1016
+ if (y > c.y1) c.y1 = y;
1017
+ for (const q of [p - 1, p + 1, p - width, p + width]) if (q >= 0 && q < dark.length && !seen[q] && dark[q] && Math.abs(q % width - x) <= 1) {
1018
+ seen[q] = 1;
1019
+ stack.push(q);
1020
+ }
1021
+ if (c.n > 4e3) break;
1022
+ }
1023
+ while (stack.length) {
1024
+ const p = stack.pop();
1025
+ seen[p] = 1;
1026
+ }
1027
+ const w = c.x1 - c.x0 + 1, h = c.y1 - c.y0 + 1;
1028
+ if (c.n > 4e3 || covered(c.x0 + c.x1 >> 1, c.y0 + c.y1 >> 1)) continue;
1029
+ if (h >= 2 && h <= 6 && w >= 4 && w <= 30 && c.n >= w * h * 0.7) {
1030
+ bars.push(c);
1031
+ continue;
1032
+ }
1033
+ if (w < 12 || h < 12 || w > 60 || h > 60 || w > h * 1.33 || h > w * 1.33) continue;
1034
+ const at = (x, y) => dark[y * width + x] === 1;
1035
+ const row = (y) => {
1036
+ let k = 0;
1037
+ for (let x = c.x0; x <= c.x1; x++) if (at(x, y)) k++;
1038
+ return k / w;
1039
+ };
1040
+ const col = (x) => {
1041
+ let k = 0;
1042
+ for (let y = c.y0; y <= c.y1; y++) if (at(x, y)) k++;
1043
+ return k / h;
1044
+ };
1045
+ const edge = (vals) => Math.max(...vals) >= 0.8;
1046
+ const top = edge([row(c.y0), row(c.y0 + 1)]), bottom = edge([row(c.y1), row(c.y1 - 1)]), left = edge([col(c.x0), col(c.x0 + 1)]), right = edge([col(c.x1), col(c.x1 - 1)]);
1047
+ let inner = 0;
1048
+ for (let y = c.y0 + Math.ceil(h * 0.25); y <= c.y1 - Math.ceil(h * 0.25); y++) for (let x = c.x0 + Math.ceil(w * 0.25); x <= c.x1 - Math.ceil(w * 0.25); x++) if (at(x, y)) inner++;
1049
+ if (top && bottom && left && right && inner === 0) squares.push(c);
1050
+ }
1051
+ squares.sort((a, b) => a.y0 - b.y0 || a.x0 - b.x0);
1052
+ const out = [];
1053
+ const used = /* @__PURE__ */ new Set();
1054
+ for (const s0 of squares) {
1055
+ if (used.has(s0)) continue;
1056
+ const run = [s0];
1057
+ used.add(s0);
1058
+ const side = s0.y1 - s0.y0 + 1, cy = (s0.y0 + s0.y1) / 2;
1059
+ let text = "\u25A1";
1060
+ for (; ; ) {
1061
+ const last = run[run.length - 1];
1062
+ const next = squares.find((q) => !used.has(q) && Math.abs((q.y0 + q.y1) / 2 - cy) <= side * 0.3 && q.x0 > last.x1 && q.x0 - last.x1 <= side * 2);
1063
+ if (!next) break;
1064
+ const gap = next.x0 - last.x1;
1065
+ const bar = bars.find((b) => b.x0 > last.x1 && b.x1 < next.x0 && Math.abs((b.y0 + b.y1) / 2 - cy) <= side * 0.3);
1066
+ let stroke = 0;
1067
+ if (!bar) for (let y = Math.round(cy - side * 0.15); y <= Math.round(cy + side * 0.15); y++) {
1068
+ let k = 0;
1069
+ for (let x = last.x1 + 1; x < next.x0; x++) {
1070
+ k = dark[y * width + x] ? k + 1 : 0;
1071
+ if (k > stroke) stroke = k;
1072
+ }
1073
+ }
1074
+ if (bar || stroke >= Math.max(4, side * 0.25)) text += "-";
1075
+ else if (gap > side) break;
1076
+ text += "\u25A1";
1077
+ used.add(next);
1078
+ run.push(next);
1079
+ }
1080
+ const x0 = run[0].x0, x1 = run[run.length - 1].x1;
1081
+ out.push({ text, x: x0, y: s0.y0, w: x1 - x0 + 1, h: side, confidence: 0.9 });
1082
+ }
1083
+ return out;
1084
+ }
1085
+ function footerInkBox(rgba, width, height, boxes) {
1086
+ const y0 = Math.floor(height * 0.88), x0 = Math.floor(width * 0.3), x1 = Math.ceil(width * 0.7);
1087
+ let minX = Infinity, maxX = -1, minY = Infinity, maxY = -1;
1088
+ for (let y = y0; y < height; y++) for (let x = x0; x < x1; x++) {
1089
+ const p = (y * width + x) * 4;
1090
+ if (rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 >= 128) continue;
1091
+ if (boxes.some((b) => x >= b.x && x < b.x + b.w && y >= b.y && y < b.y + b.h)) continue;
1092
+ if (x < minX) minX = x;
1093
+ if (x > maxX) maxX = x;
1094
+ if (y < minY) minY = y;
1095
+ if (y > maxY) maxY = y;
1096
+ }
1097
+ if (maxX < 0) return null;
1098
+ const bh = maxY - minY + 1;
1099
+ if (bh < height * 5e-3 || bh > height * 0.025 || maxX - minX + 1 > width * 0.2) return null;
1100
+ const pad = 4, bx = Math.max(0, minX - pad), by = Math.max(0, minY - pad);
1101
+ return { x: bx, y: by, w: Math.min(width, maxX + pad + 1) - bx, h: Math.min(height, maxY + pad + 1) - by };
1102
+ }
1103
+ function closingParens(rgba, width, items) {
1104
+ const out = [];
1105
+ const dark = (x, y) => {
1106
+ const p = (y * width + x) * 4;
1107
+ return rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 < 128;
1108
+ };
1109
+ for (const it of items) {
1110
+ const t = it.text.replace(/\s+$/, "");
1111
+ if ((t.match(/\(/g)?.length ?? 0) <= (t.match(/\)/g)?.length ?? 0) || !/\([^()]*$/.test(t)) continue;
1112
+ const x0 = it.x + it.w + 2;
1113
+ const next = items.filter((o) => o !== it && o.x >= x0 && o.y < it.y + it.h && o.y + o.h > it.y).reduce((m, o) => Math.min(m, o.x), Infinity);
1114
+ const x1 = Math.min(width, next, x0 + it.h * 8);
1115
+ let minX = Infinity, maxX = -1, minY = Infinity, maxY = -1, cols = 0, prevOn = false, runs = 0;
1116
+ for (let x = x0; x < x1; x++) {
1117
+ let on = false;
1118
+ for (let y = it.y; y < it.y + it.h; y++) if (dark(x, y)) {
1119
+ on = true;
1120
+ if (y < minY) minY = y;
1121
+ if (y > maxY) maxY = y;
1122
+ }
1123
+ if (on) {
1124
+ cols++;
1125
+ if (!prevOn) runs++;
1126
+ if (x < minX) minX = x;
1127
+ maxX = x;
1128
+ }
1129
+ prevOn = on;
1130
+ }
1131
+ if (runs !== 1 || maxX - minX + 1 > it.h * 0.5 || maxY - minY + 1 < it.h * 0.6) continue;
1132
+ let rule = false;
1133
+ for (let x = minX; x <= maxX && !rule; x++) rule = minY > 1 && dark(x, minY - 2) || dark(x, Math.min(maxY + 2, Math.floor(rgba.length / 4 / width) - 1));
1134
+ if (rule) continue;
1135
+ const meanX = (ya, yb) => {
1136
+ let sx = 0, k = 0;
1137
+ for (let y = ya; y < yb; y++) for (let x = minX; x <= maxX; x++) if (dark(x, y)) {
1138
+ sx += x;
1139
+ k++;
1140
+ }
1141
+ return k ? sx / k : NaN;
1142
+ };
1143
+ const ch = maxY - minY + 1, band = Math.max(1, Math.round(ch * 0.2));
1144
+ const ends = (meanX(minY, minY + band) + meanX(maxY + 1 - band, maxY + 1)) / 2, mid = meanX(minY + Math.floor(ch * 0.4), minY + Math.ceil(ch * 0.6));
1145
+ if (!(mid - ends >= 0.8)) continue;
1146
+ out.push({ text: ")", x: minX, y: minY, w: maxX - minX + 1, h: maxY - minY + 1, confidence: it.confidence });
1147
+ }
1148
+ return out;
1149
+ }
872
1150
  var OcrEngine = class _OcrEngine {
873
1151
  det;
874
1152
  rec;
@@ -958,6 +1236,7 @@ var OcrEngine = class _OcrEngine {
958
1236
  const detected = await this.detect(rgba, width, height, tuning, stats);
959
1237
  const rows = rowRules.length ? detected.flatMap((b) => splitBoxAtRowRules(b, rowRules)) : detected;
960
1238
  const boxes = cellRules.length ? rows.flatMap((b) => splitBoxAtCellRules(b, cellRules)) : rows;
1239
+ const footer = tuning.postprocess ? footerInkBox(rgba, width, height, boxes) : null;
961
1240
  const jobs = [];
962
1241
  const joins = [];
963
1242
  let group = 0;
@@ -1001,6 +1280,7 @@ var OcrEngine = class _OcrEngine {
1001
1280
  if (keep) jobs.push({ box: b, rot: 0, group, keep });
1002
1281
  jobs.push({ box: b, rot: 0, group: group++ });
1003
1282
  }
1283
+ if (footer) jobs.push({ box: footer, rot: 0, group: group++, footer: true });
1004
1284
  const results = await this.recognizeJobs(rgba, width, jobs, tuning.recBatch);
1005
1285
  const best = /* @__PURE__ */ new Map();
1006
1286
  const score = (job, confidence) => confidence - (job.keep ? KEEP_MARGIN : 0);
@@ -1010,6 +1290,12 @@ var OcrEngine = class _OcrEngine {
1010
1290
  const cur = best.get(job.group);
1011
1291
  if (!cur || score(job, r.confidence) > score(cur.job, cur.confidence)) best.set(job.group, { job, ...r });
1012
1292
  });
1293
+ jobs.forEach((job, i) => {
1294
+ const r = results[i], cur = best.get(job.group);
1295
+ if (!job.keep || !r || !cur || cur.job === job) return;
1296
+ const b = cur.text.replace(/\s/g, "");
1297
+ if (r.text.replace(/\s/g, "") === "\xB7" + b && /^[가-힣]/.test(b)) best.set(job.group, { ...cur, text: "\xB7" + cur.text, steps: [r.steps[0], ...cur.steps] });
1298
+ });
1013
1299
  let items = [];
1014
1300
  for (const r of best.values()) {
1015
1301
  const { job, confidence, stepPx } = r;
@@ -1018,7 +1304,11 @@ var OcrEngine = class _OcrEngine {
1018
1304
  const raw = tuning.postprocess && job.rot === 0 ? restoreGlyphs(rgba, width, job.box, read, steps, stepPx, note) : read;
1019
1305
  let text = tuning.postprocess ? restoreSymbols(raw.trim(), note.ringLead) : raw;
1020
1306
  if (!text.trim()) continue;
1021
- if (tuning.postprocess && job.rot === 0 && !/^[◎●▪□■▣❐❏○ㅇ]/.test(text)) {
1307
+ if (tuning.postprocess && job.rot === 0 && text !== "/" && /^[(:;/)]+$/.test(text) && text.includes("/")) {
1308
+ const g = grayCrop(rgba, width, job.box);
1309
+ if (tallInkCount(g, job.box.w, job.box.h, inkStats(g)) === 1) text = "/";
1310
+ }
1311
+ if (tuning.postprocess && job.rot === 0 && !/^[◎●▪□■▣❐❏○ㅇ◆◇◈]/.test(text)) {
1022
1312
  const chars = [...read], k = chars.findIndex((c) => c.trim());
1023
1313
  if (k >= 0 && steps.length === chars.length) {
1024
1314
  const g = grayCrop(rgba, width, job.box);
@@ -1028,6 +1318,8 @@ var OcrEngine = class _OcrEngine {
1028
1318
  if (b?.mark === "\u25CE" && b.covers && /^[Oo0○]/.test(text)) text = b.mark + " " + text.slice(1).trimStart();
1029
1319
  else if (b?.mark === "\u25A1" || b?.mark === "\u25A3") {
1030
1320
  if (!b.covers && body) text = b.mark + " " + text;
1321
+ } else if (b?.mark === "\u25C6" || b?.mark === "\u25C7" || b?.mark === "\u25C8") {
1322
+ if (b.covers ? /^[\p{S}\p{P}]/u.test(text) : body) text = b.covers ? b.mark + " " + text.slice(1).trimStart() : b.mark + " " + text;
1031
1323
  } else if (b?.mark === "\u2023") {
1032
1324
  if (b.covers ? text.startsWith("\u2192") : body) text = b.covers ? b.mark + " " + text.slice(1).trimStart() : b.mark + " " + text;
1033
1325
  } else if (b?.mark === "\u2750" || b?.mark === "\u274F") {
@@ -1045,6 +1337,10 @@ var OcrEngine = class _OcrEngine {
1045
1337
  const g = grayCrop(rgba, width, job.box);
1046
1338
  text = arrowGlyph(g, job.box.w, job.box.h, inkStats(g)) ?? text;
1047
1339
  }
1340
+ if (job.footer) {
1341
+ if (!/^[-\u2013\u2014]?\s*(?:\d{1,4}|[ivxIVXⅰ-ⅹⅠ-Ⅹ]{1,4})\s*[-\u2013\u2014]?$/.test(text.trim())) continue;
1342
+ text = text.replace(/[\u2013\u2014]/g, "-");
1343
+ }
1048
1344
  if (tuning.postprocess && isDotFragment(text)) continue;
1049
1345
  if (confidence < tuning.textScore) {
1050
1346
  if (stats) {
@@ -1083,6 +1379,19 @@ var OcrEngine = class _OcrEngine {
1083
1379
  if (leaderEnds.size) items = joinLeaderItems(items, leaderEnds);
1084
1380
  if (tuning.postprocess) items = dropNestedFragments(items);
1085
1381
  if (tuning.postprocess) for (const it of items) this.outerSquare(rgba, width, it, items);
1382
+ if (tuning.postprocess) items.push(...closingParens(rgba, width, items));
1383
+ if (tuning.postprocess) items.push(...placeholderSquares(rgba, width, height, items));
1384
+ if (tuning.postprocess) items.push(...rowHeadDashes(rgba, width, items));
1385
+ if (tuning.postprocess) {
1386
+ const tails = rowTailBoxes(rgba, width, items);
1387
+ if (tails.length) {
1388
+ const res = await this.recognizeJobs(rgba, width, tails.map((box, k) => ({ box, rot: 0, group: k })), tuning.recBatch);
1389
+ tails.forEach((box, k) => {
1390
+ const t = res[k]?.text.trim() ?? "";
1391
+ if (/^\d{1,4}$/.test(t) && (res[k]?.confidence ?? 0) >= tuning.textScore) items.push({ text: t, ...this.itemBox(rgba, width, box, tuning), confidence: res[k].confidence });
1392
+ });
1393
+ }
1394
+ }
1086
1395
  if (tuning.postprocess) restoreBulletItems(items);
1087
1396
  items.sort((a, b) => a.y - b.y || a.x - b.x);
1088
1397
  return items;
@@ -1752,4 +2061,4 @@ export {
1752
2061
  groupOcrLines,
1753
2062
  ocrItemsToBlocks
1754
2063
  };
1755
- //# sourceMappingURL=chunk-FJ3IKKDV.js.map
2064
+ //# sourceMappingURL=chunk-DULJ7PPP.js.map