kordoc 3.9.0 → 3.10.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 (38) hide show
  1. package/README.md +27 -0
  2. package/dist/{-6CLKMLK2.js → -3B5FDXW2.js} +18 -12
  3. package/dist/{chunk-XKDA4FDM.js → chunk-5DL6VCIJ.js} +4 -120
  4. package/dist/chunk-5DL6VCIJ.js.map +1 -0
  5. package/dist/{chunk-ITPZD7XK.js → chunk-5TK4X4JQ.js} +32 -313
  6. package/dist/chunk-5TK4X4JQ.js.map +1 -0
  7. package/dist/chunk-FU25KFFZ.js +938 -0
  8. package/dist/chunk-FU25KFFZ.js.map +1 -0
  9. package/dist/chunk-MZA7AXHN.js +124 -0
  10. package/dist/chunk-MZA7AXHN.js.map +1 -0
  11. package/dist/{chunk-EZ5GBTBE.js → chunk-PNXOUDS7.js} +2 -2
  12. package/dist/{chunk-EZ5GBTBE.js.map → chunk-PNXOUDS7.js.map} +1 -1
  13. package/dist/{chunk-VHXUD3PW.cjs → chunk-ZQOGTAT5.cjs} +2 -2
  14. package/dist/{chunk-VHXUD3PW.cjs.map → chunk-ZQOGTAT5.cjs.map} +1 -1
  15. package/dist/cli.js +33 -6
  16. package/dist/cli.js.map +1 -1
  17. package/dist/index.cjs +798 -174
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +40 -1
  20. package/dist/index.d.ts +40 -1
  21. package/dist/index.js +680 -56
  22. package/dist/index.js.map +1 -1
  23. package/dist/mcp.js +8 -5
  24. package/dist/mcp.js.map +1 -1
  25. package/dist/{parser-N4G5KQBE.cjs → parser-6B7BUSX3.cjs} +14 -14
  26. package/dist/{parser-N4G5KQBE.cjs.map → parser-6B7BUSX3.cjs.map} +1 -1
  27. package/dist/{parser-NCNME2Z6.js → parser-DKIA66MN.js} +2 -2
  28. package/dist/{parser-LVI45MVF.js → parser-VCJTQVAH.js} +8 -6
  29. package/dist/{parser-LVI45MVF.js.map → parser-VCJTQVAH.js.map} +1 -1
  30. package/dist/render-4I72JOAR.js +9 -0
  31. package/dist/render-4I72JOAR.js.map +1 -0
  32. package/dist/{watch-XSLV62BH.js → watch-MQTMNUSB.js} +6 -4
  33. package/dist/{watch-XSLV62BH.js.map → watch-MQTMNUSB.js.map} +1 -1
  34. package/package.json +2 -2
  35. package/dist/chunk-ITPZD7XK.js.map +0 -1
  36. package/dist/chunk-XKDA4FDM.js.map +0 -1
  37. /package/dist/{-6CLKMLK2.js.map → -3B5FDXW2.js.map} +0 -0
  38. /package/dist/{parser-NCNME2Z6.js.map → parser-DKIA66MN.js.map} +0 -0
package/dist/index.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  sanitizeHref,
20
20
  stripDtd,
21
21
  toArrayBuffer
22
- } from "./chunk-EZ5GBTBE.js";
22
+ } from "./chunk-PNXOUDS7.js";
23
23
  import {
24
24
  parsePageRange
25
25
  } from "./chunk-GE43BE46.js";
@@ -478,9 +478,9 @@ async function extractHwpxStyles(zip, decompressed) {
478
478
  function parseCharProperties(doc, map) {
479
479
  const tagNames = ["hh:charPr", "charPr", "hp:charPr"];
480
480
  for (const tagName of tagNames) {
481
- const elements = doc.getElementsByTagName(tagName);
482
- for (let i = 0; i < elements.length; i++) {
483
- const el = elements[i];
481
+ const elements2 = doc.getElementsByTagName(tagName);
482
+ for (let i = 0; i < elements2.length; i++) {
483
+ const el = elements2[i];
484
484
  const id = el.getAttribute("id") || el.getAttribute("IDRef") || "";
485
485
  if (!id) continue;
486
486
  const prop = {};
@@ -514,9 +514,9 @@ function parseCharProperties(doc, map) {
514
514
  function parseStyleElements(doc, map) {
515
515
  const tagNames = ["hh:style", "style", "hp:style"];
516
516
  for (const tagName of tagNames) {
517
- const elements = doc.getElementsByTagName(tagName);
518
- for (let i = 0; i < elements.length; i++) {
519
- const el = elements[i];
517
+ const elements2 = doc.getElementsByTagName(tagName);
518
+ for (let i = 0; i < elements2.length; i++) {
519
+ const el = elements2[i];
520
520
  const id = el.getAttribute("id") || el.getAttribute("IDRef") || String(i);
521
521
  const name = el.getAttribute("name") || el.getAttribute("engName") || "";
522
522
  const charPrId = el.getAttribute("charPrIDRef") || void 0;
@@ -528,9 +528,9 @@ function parseStyleElements(doc, map) {
528
528
  function parseNumberings(doc, map) {
529
529
  const tagNames = ["hh:numbering", "numbering"];
530
530
  for (const tagName of tagNames) {
531
- const elements = doc.getElementsByTagName(tagName);
532
- for (let i = 0; i < elements.length; i++) {
533
- const el = elements[i];
531
+ const elements2 = doc.getElementsByTagName(tagName);
532
+ for (let i = 0; i < elements2.length; i++) {
533
+ const el = elements2[i];
534
534
  const id = el.getAttribute("id") || "";
535
535
  if (!id) continue;
536
536
  const def = { heads: /* @__PURE__ */ new Map() };
@@ -557,9 +557,9 @@ function parseNumberings(doc, map) {
557
557
  function parseBullets(doc, map) {
558
558
  const tagNames = ["hh:bullet", "bullet"];
559
559
  for (const tagName of tagNames) {
560
- const elements = doc.getElementsByTagName(tagName);
561
- for (let i = 0; i < elements.length; i++) {
562
- const el = elements[i];
560
+ const elements2 = doc.getElementsByTagName(tagName);
561
+ for (let i = 0; i < elements2.length; i++) {
562
+ const el = elements2[i];
563
563
  const id = el.getAttribute("id") || "";
564
564
  const char = el.getAttribute("char") || "";
565
565
  if (id && char) map.set(id, char);
@@ -570,9 +570,9 @@ function parseBullets(doc, map) {
570
570
  function parseParaHeadings(doc, map) {
571
571
  const tagNames = ["hh:paraPr", "paraPr"];
572
572
  for (const tagName of tagNames) {
573
- const elements = doc.getElementsByTagName(tagName);
574
- for (let i = 0; i < elements.length; i++) {
575
- const el = elements[i];
573
+ const elements2 = doc.getElementsByTagName(tagName);
574
+ for (let i = 0; i < elements2.length; i++) {
575
+ const el = elements2[i];
576
576
  const id = el.getAttribute("id") || "";
577
577
  if (!id) continue;
578
578
  const heading = findChildByLocalName(el, "heading");
@@ -2505,11 +2505,11 @@ function formatRoman(n, upper) {
2505
2505
  const values = [1e3, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
2506
2506
  const symbols = upper ? ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"] : ["m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i"];
2507
2507
  let result = "";
2508
- let num = n;
2508
+ let num2 = n;
2509
2509
  for (let i = 0; i < values.length; i++) {
2510
- while (num >= values[i]) {
2510
+ while (num2 >= values[i]) {
2511
2511
  result += symbols[i];
2512
- num -= values[i];
2512
+ num2 -= values[i];
2513
2513
  }
2514
2514
  }
2515
2515
  return result;
@@ -2517,11 +2517,11 @@ function formatRoman(n, upper) {
2517
2517
  function formatLatin(n, upper) {
2518
2518
  if (n <= 0) return "";
2519
2519
  let result = "";
2520
- let num = n;
2521
- while (num > 0) {
2522
- num--;
2523
- result = String.fromCharCode((upper ? 65 : 97) + num % 26) + result;
2524
- num = Math.floor(num / 26);
2520
+ let num2 = n;
2521
+ while (num2 > 0) {
2522
+ num2--;
2523
+ result = String.fromCharCode((upper ? 65 : 97) + num2 % 26) + result;
2524
+ num2 = Math.floor(num2 / 26);
2525
2525
  }
2526
2526
  return result;
2527
2527
  }
@@ -2529,15 +2529,15 @@ function formatEastAsianNumber(n, digits, units, zero) {
2529
2529
  if (n === 0) return zero;
2530
2530
  if (n < 0 || n > 99999) return String(n);
2531
2531
  let result = "";
2532
- let num = n;
2532
+ let num2 = n;
2533
2533
  let unit = 0;
2534
- while (num > 0) {
2535
- const d = num % 10;
2534
+ while (num2 > 0) {
2535
+ const d = num2 % 10;
2536
2536
  if (d > 0) {
2537
2537
  const digitStr = d === 1 && unit > 0 ? "" : digits[d];
2538
2538
  result = digitStr + units[unit] + result;
2539
2539
  }
2540
- num = Math.floor(num / 10);
2540
+ num2 = Math.floor(num2 / 10);
2541
2541
  unit++;
2542
2542
  }
2543
2543
  return result;
@@ -2584,8 +2584,8 @@ function expandNumberingFormat(formatStr, counters, numbering) {
2584
2584
  const idx = levelRef - 1;
2585
2585
  const counterVal = counters[idx] ?? 0;
2586
2586
  const start = numbering.startNumbers[idx] ?? 1;
2587
- const num = counterVal > 0 ? start - 1 + counterVal : start;
2588
- result += formatNumber(num, headFormatToNumFmt(numbering.numberFormats[idx] ?? 0));
2587
+ const num2 = counterVal > 0 ? start - 1 + counterVal : start;
2588
+ result += formatNumber(num2, headFormatToNumFmt(numbering.numberFormats[idx] ?? 0));
2589
2589
  i += 2;
2590
2590
  continue;
2591
2591
  }
@@ -4153,11 +4153,11 @@ function applyCtrlEffect(ctrl, records, ctx) {
4153
4153
  const attr = ctrl.data.readUInt32LE(4);
4154
4154
  const type = attr & 15;
4155
4155
  const format = attr >>> 4 & 255;
4156
- const num = ctx.doc.autoCounters.get(type) ?? 1;
4157
- ctx.doc.autoCounters.set(type, num + 1);
4156
+ const num2 = ctx.doc.autoCounters.get(type) ?? 1;
4157
+ ctx.doc.autoCounters.set(type, num2 + 1);
4158
4158
  const prefix = ctrl.data.length >= 14 ? wcharAt(ctrl.data, 12) : "";
4159
4159
  const suffix = ctrl.data.length >= 16 ? wcharAt(ctrl.data, 14) : "";
4160
- ctrl.inlineText = `${prefix}${formatNumber(num, shapeFormatToNumFmt(format))}${suffix}`;
4160
+ ctrl.inlineText = `${prefix}${formatNumber(num2, shapeFormatToNumFmt(format))}${suffix}`;
4161
4161
  }
4162
4162
  return;
4163
4163
  }
@@ -4165,8 +4165,8 @@ function applyCtrlEffect(ctrl, records, ctx) {
4165
4165
  if (ctrl.data.length >= 10) {
4166
4166
  const attr = ctrl.data.readUInt32LE(4);
4167
4167
  const type = attr & 15;
4168
- const num = ctrl.data.readUInt16LE(8);
4169
- if (num > 0) ctx.doc.autoCounters.set(type, num);
4168
+ const num2 = ctrl.data.readUInt16LE(8);
4169
+ if (num2 > 0) ctx.doc.autoCounters.set(type, num2);
4170
4170
  }
4171
4171
  return;
4172
4172
  }
@@ -4228,7 +4228,7 @@ function blocksPlainText(blocks, sep) {
4228
4228
  return parts.join(sep).trim();
4229
4229
  }
4230
4230
  function applyNoteEffect(ctrl, records, ctx, autoType) {
4231
- const num = ctx.doc.autoCounters.get(autoType) ?? 1;
4231
+ const num2 = ctx.doc.autoCounters.get(autoType) ?? 1;
4232
4232
  let before = "";
4233
4233
  let after = "";
4234
4234
  let shape = 0;
@@ -4239,11 +4239,11 @@ function applyNoteEffect(ctrl, records, ctx, autoType) {
4239
4239
  if (ctrl.data.length >= 16) {
4240
4240
  shape = ctrl.data.readUInt32LE(12) & 255;
4241
4241
  }
4242
- const formatted = formatNumber(num, shapeFormatToNumFmt(shape));
4242
+ const formatted = formatNumber(num2, shapeFormatToNumFmt(shape));
4243
4243
  const marker = before || after ? `${before}${formatted}${after}` : `${formatted})`;
4244
4244
  const content = blocksPlainText(parseListHeaderParagraphs(ctrl, records, ctx), " ");
4245
- if ((ctx.doc.autoCounters.get(autoType) ?? 1) <= num) {
4246
- ctx.doc.autoCounters.set(autoType, num + 1);
4245
+ if ((ctx.doc.autoCounters.get(autoType) ?? 1) <= num2) {
4246
+ ctx.doc.autoCounters.set(autoType, num2 + 1);
4247
4247
  }
4248
4248
  ctrl.inlineText = marker;
4249
4249
  if (content) ctrl.footnote = content.startsWith(marker) ? content : `${marker} ${content}`;
@@ -16781,9 +16781,9 @@ var MAX_ROWS2 = 1e4;
16781
16781
  var MAX_COLS2 = 200;
16782
16782
  function cleanNumericValue(raw) {
16783
16783
  if (!/^-?\d+\.\d+$/.test(raw)) return raw;
16784
- const num = parseFloat(raw);
16785
- if (!isFinite(num)) return raw;
16786
- const cleaned = parseFloat(num.toPrecision(15)).toString();
16784
+ const num2 = parseFloat(raw);
16785
+ if (!isFinite(num2)) return raw;
16786
+ const cleaned = parseFloat(num2.toPrecision(15)).toString();
16787
16787
  return cleaned;
16788
16788
  }
16789
16789
  function parseCellRef(ref) {
@@ -17126,17 +17126,17 @@ function decodeRk(rk) {
17126
17126
  const fDiv100 = (rk & 1) !== 0;
17127
17127
  const fInt = (rk & 2) !== 0;
17128
17128
  const val30 = rk >> 2;
17129
- let num;
17129
+ let num2;
17130
17130
  if (fInt) {
17131
- num = val30;
17131
+ num2 = val30;
17132
17132
  } else {
17133
17133
  const high32 = (rk & 4294967292) >>> 0;
17134
17134
  const buf = Buffer.alloc(8);
17135
17135
  buf.writeUInt32LE(0, 0);
17136
17136
  buf.writeUInt32LE(high32, 4);
17137
- num = buf.readDoubleLE(0);
17137
+ num2 = buf.readDoubleLE(0);
17138
17138
  }
17139
- return fDiv100 ? num / 100 : num;
17139
+ return fDiv100 ? num2 / 100 : num2;
17140
17140
  }
17141
17141
  function decodeMulRk(data) {
17142
17142
  if (data.length < 6) return null;
@@ -17836,9 +17836,9 @@ function nodeToLatex(el) {
17836
17836
  case "f": {
17837
17837
  const n = firstKid(el, "num");
17838
17838
  const d = firstKid(el, "den");
17839
- const num = n ? childrenToLatex(n) : "";
17839
+ const num2 = n ? childrenToLatex(n) : "";
17840
17840
  const den = d ? childrenToLatex(d) : "";
17841
- return "\\frac" + grp(num) + grp(den);
17841
+ return "\\frac" + grp(num2) + grp(den);
17842
17842
  }
17843
17843
  // 첨자
17844
17844
  case "sSup": {
@@ -20479,10 +20479,10 @@ function simulateWrap(text, firstWidth, contWidth, height, ratioPct, mode = "kee
20479
20479
  const spacing = opts?.spacingPct ?? 0;
20480
20480
  const k = height * ratioPct / 100 / 1e3;
20481
20481
  const cwCp = (cp) => (cp === 32 ? spaceEm : charWidthEm1000(cp)) * (1 + spacing / 100) * k;
20482
- const charW = (ch) => cwCp(ch.codePointAt(0));
20482
+ const charW2 = (ch) => cwCp(ch.codePointAt(0));
20483
20483
  const rangeW = (from, to) => {
20484
20484
  let w = 0;
20485
- for (const ch of text.slice(from, to)) w += charW(ch);
20485
+ for (const ch of text.slice(from, to)) w += charW2(ch);
20486
20486
  return w;
20487
20487
  };
20488
20488
  const units = text.match(mode === "keep" ? / +|[^ ]+/g : / +|[^ ]/g) ?? [];
@@ -20503,7 +20503,7 @@ function simulateWrap(text, firstWidth, contWidth, height, ratioPct, mode = "kee
20503
20503
  };
20504
20504
  for (const u of units) {
20505
20505
  if (u[0] === " ") {
20506
- lineW += charW(" ") * u.length;
20506
+ lineW += charW2(" ") * u.length;
20507
20507
  pos += u.length;
20508
20508
  continue;
20509
20509
  }
@@ -20516,7 +20516,7 @@ function simulateWrap(text, firstWidth, contWidth, height, ratioPct, mode = "kee
20516
20516
  if (lineW === 0 || w > contWidth + EPS) {
20517
20517
  let sub = 0;
20518
20518
  for (const ch of u) {
20519
- const c = charW(ch);
20519
+ const c = charW2(ch);
20520
20520
  if (lineW + c > avail + EPS && lineW > 0) breakBefore(pos + sub, 0);
20521
20521
  lineW += c;
20522
20522
  sub += ch.length;
@@ -21920,9 +21920,9 @@ function readCommand(input, idx, depth) {
21920
21920
  const command = name.value;
21921
21921
  if (command === "\\") return { value: "#", next: name.next };
21922
21922
  if (command === "frac") {
21923
- const num = readGroupOrToken(input, name.next, depth);
21924
- const den = readGroupOrToken(input, num.next, depth);
21925
- return { value: `{${num.value}} over {${den.value}}`, next: den.next };
21923
+ const num2 = readGroupOrToken(input, name.next, depth);
21924
+ const den = readGroupOrToken(input, num2.next, depth);
21925
+ return { value: `{${num2.value}} over {${den.value}}`, next: den.next };
21926
21926
  }
21927
21927
  if (command === "sqrt") {
21928
21928
  let cursor = skipSpaces(input, name.next);
@@ -24838,6 +24838,629 @@ async function blocksToPdf(blocks, options) {
24838
24838
  return markdownToPdf(markdown, options);
24839
24839
  }
24840
24840
 
24841
+ // src/render/svg-render.ts
24842
+ import JSZip10 from "jszip";
24843
+
24844
+ // src/render/layout.ts
24845
+ function toInt32(v, fallback = 0) {
24846
+ if (v == null || v === "") return fallback;
24847
+ const n = Number(v);
24848
+ if (!Number.isFinite(n)) return fallback;
24849
+ return n > 2147483647 ? n - 4294967296 : n;
24850
+ }
24851
+ function solveBoundaries(constraints, count, total) {
24852
+ const x = new Array(count + 1).fill(void 0);
24853
+ x[0] = 0;
24854
+ if (total != null && total > 0) x[count] = total;
24855
+ let changed = true;
24856
+ let guard = 0;
24857
+ while (changed && guard++ < count + 8) {
24858
+ changed = false;
24859
+ for (const c of constraints) {
24860
+ if (c.a < 0 || c.b > count || c.a >= c.b) continue;
24861
+ const xa = x[c.a];
24862
+ const xb = x[c.b];
24863
+ if (xa != null && xb == null) {
24864
+ x[c.b] = xa + c.size;
24865
+ changed = true;
24866
+ } else if (xb != null && xa == null) {
24867
+ x[c.a] = xb - c.size;
24868
+ changed = true;
24869
+ }
24870
+ }
24871
+ }
24872
+ let i = 0;
24873
+ while (i <= count) {
24874
+ if (x[i] != null) {
24875
+ i++;
24876
+ continue;
24877
+ }
24878
+ let lo = i - 1;
24879
+ let hi = i;
24880
+ while (hi <= count && x[hi] == null) hi++;
24881
+ const loV = x[lo];
24882
+ const hiV = hi <= count ? x[hi] : loV + (hi - lo) * 1e3;
24883
+ const n = hi - lo;
24884
+ for (let k = 1; k < n; k++) x[lo + k] = loV + (hiV - loV) * k / n;
24885
+ if (hi > count) x[count] = hiV;
24886
+ i = hi;
24887
+ }
24888
+ const out = x;
24889
+ for (let k = 1; k <= count; k++) if (out[k] < out[k - 1]) out[k] = out[k - 1];
24890
+ return out;
24891
+ }
24892
+ function solveRowHeights(cells, rowCount) {
24893
+ const h = new Array(rowCount).fill(0);
24894
+ for (const c of cells) {
24895
+ if (c.rowSpan === 1 && c.rowAddr >= 0 && c.rowAddr < rowCount) {
24896
+ h[c.rowAddr] = Math.max(h[c.rowAddr], c.height);
24897
+ }
24898
+ }
24899
+ for (const c of cells) {
24900
+ if (c.rowSpan <= 1) continue;
24901
+ const rows = [];
24902
+ for (let r = c.rowAddr; r < Math.min(c.rowAddr + c.rowSpan, rowCount); r++) rows.push(r);
24903
+ const known = rows.reduce((s, r) => s + h[r], 0);
24904
+ const missing = rows.filter((r) => h[r] === 0);
24905
+ if (missing.length > 0 && c.height > known) {
24906
+ const each = (c.height - known) / missing.length;
24907
+ for (const r of missing) h[r] = each;
24908
+ }
24909
+ }
24910
+ for (const c of cells) {
24911
+ if (c.rowSpan === 1 && c.contentH != null && c.rowAddr >= 0 && c.rowAddr < rowCount) {
24912
+ if (c.contentH > h[c.rowAddr]) h[c.rowAddr] = c.contentH;
24913
+ }
24914
+ }
24915
+ return h;
24916
+ }
24917
+
24918
+ // src/render/head-styles.ts
24919
+ var DEFAULT_CHAR = { height: 1e3, bold: false, italic: false, underline: false, ratio: 100, spacing: 0 };
24920
+ function borderWidthPt(v) {
24921
+ const n = parseFloat(v ?? "");
24922
+ if (!Number.isFinite(n)) return 0.34;
24923
+ return n * 2.834645;
24924
+ }
24925
+ function parseEdge(el) {
24926
+ if (!el) return void 0;
24927
+ const type = el.getAttribute("type") ?? "NONE";
24928
+ if (type === "NONE") return void 0;
24929
+ return { type, widthPt: borderWidthPt(el.getAttribute("width")), color: el.getAttribute("color") ?? "#000000" };
24930
+ }
24931
+ function parseRenderStyles(headXml) {
24932
+ const styles = { charPr: /* @__PURE__ */ new Map(), paraAlign: /* @__PURE__ */ new Map(), borderFill: /* @__PURE__ */ new Map() };
24933
+ const doc = createXmlParser().parseFromString(headXml, "text/xml");
24934
+ const root = doc.documentElement;
24935
+ if (!root) return styles;
24936
+ const walk = (el) => {
24937
+ const tag = (el.tagName || "").replace(/^[^:]+:/, "");
24938
+ if (tag === "charPr") {
24939
+ const id = el.getAttribute("id");
24940
+ if (id != null) {
24941
+ const ratioEl = findChildByLocalName(el, "ratio");
24942
+ const spacingEl = findChildByLocalName(el, "spacing");
24943
+ const underlineEl = findChildByLocalName(el, "underline");
24944
+ const textColor = el.getAttribute("textColor");
24945
+ styles.charPr.set(id, {
24946
+ height: Number(el.getAttribute("height")) || 1e3,
24947
+ bold: findChildByLocalName(el, "bold") != null,
24948
+ italic: findChildByLocalName(el, "italic") != null,
24949
+ underline: underlineEl != null && (underlineEl.getAttribute("type") ?? "NONE") !== "NONE",
24950
+ color: textColor && textColor !== "#000000" && textColor.toLowerCase() !== "none" ? textColor : void 0,
24951
+ ratio: Number(ratioEl?.getAttribute("hangul")) || 100,
24952
+ spacing: Number(spacingEl?.getAttribute("hangul")) || 0
24953
+ });
24954
+ }
24955
+ } else if (tag === "paraPr") {
24956
+ const id = el.getAttribute("id");
24957
+ if (id != null) {
24958
+ const align = findChildByLocalName(el, "align");
24959
+ styles.paraAlign.set(id, align?.getAttribute("horizontal") || "JUSTIFY");
24960
+ }
24961
+ } else if (tag === "borderFill") {
24962
+ const id = el.getAttribute("id");
24963
+ if (id != null) {
24964
+ const bf = {
24965
+ left: parseEdge(findChildByLocalName(el, "leftBorder")),
24966
+ right: parseEdge(findChildByLocalName(el, "rightBorder")),
24967
+ top: parseEdge(findChildByLocalName(el, "topBorder")),
24968
+ bottom: parseEdge(findChildByLocalName(el, "bottomBorder"))
24969
+ };
24970
+ const fillBrush = findChildByLocalName(el, "fillBrush");
24971
+ const winBrush = fillBrush ? findChildByLocalName(fillBrush, "winBrush") : null;
24972
+ const face = winBrush?.getAttribute("faceColor");
24973
+ if (face && face.toLowerCase() !== "none") bf.fill = face;
24974
+ styles.borderFill.set(id, bf);
24975
+ }
24976
+ }
24977
+ const children = el.childNodes;
24978
+ for (let i = 0; i < children.length; i++) {
24979
+ const ch = children[i];
24980
+ if (ch.nodeType === 1) walk(ch);
24981
+ }
24982
+ };
24983
+ walk(root);
24984
+ return styles;
24985
+ }
24986
+
24987
+ // src/render/svg-render.ts
24988
+ function ln(el) {
24989
+ return (el.tagName || "").replace(/^[^:]+:/, "");
24990
+ }
24991
+ function elements(el) {
24992
+ const out = [];
24993
+ const children = el.childNodes;
24994
+ if (!children) return out;
24995
+ for (let i = 0; i < children.length; i++) {
24996
+ if (children[i].nodeType === 1) out.push(children[i]);
24997
+ }
24998
+ return out;
24999
+ }
25000
+ function num(el, attr, fallback = 0) {
25001
+ return el ? toInt32(el.getAttribute(attr) ?? void 0, fallback) : fallback;
25002
+ }
25003
+ function findFirst(el, name, depth = 0) {
25004
+ if (depth > 64) return null;
25005
+ for (const ch of elements(el)) {
25006
+ if (ln(ch) === name) return ch;
25007
+ const found = findFirst(ch, name, depth + 1);
25008
+ if (found) return found;
25009
+ }
25010
+ return null;
25011
+ }
25012
+ function escapeXml3(s) {
25013
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
25014
+ }
25015
+ var OBJ_TAGS = /* @__PURE__ */ new Set(["tbl", "pic", "container", "equation", "rect", "ellipse", "polygon", "curv", "line", "arc", "ole", "textart"]);
25016
+ var pt = (u) => String(Math.round(u) / 100);
25017
+ function warnOnce(ctx, key, msg2) {
25018
+ if (ctx.warned.has(key)) return;
25019
+ ctx.warned.add(key);
25020
+ ctx.warnings.push(msg2);
25021
+ }
25022
+ function textOfT(t) {
25023
+ let s = "";
25024
+ const walk = (n, d) => {
25025
+ if (d > 32) return;
25026
+ const kids2 = n.childNodes;
25027
+ if (!kids2) return;
25028
+ for (let i = 0; i < kids2.length; i++) {
25029
+ const c = kids2[i];
25030
+ if (c.nodeType === 3) s += c.textContent ?? "";
25031
+ else if (c.nodeType === 1) walk(c, d + 1);
25032
+ }
25033
+ };
25034
+ walk(t, 0);
25035
+ return s;
25036
+ }
25037
+ function buildPara(p) {
25038
+ const chars = [];
25039
+ const objs = [];
25040
+ let segs = [];
25041
+ for (const runEl of elements(p)) {
25042
+ const tag = ln(runEl);
25043
+ if (tag === "run") {
25044
+ const prId = runEl.getAttribute("charPrIDRef");
25045
+ for (const ch of elements(runEl)) {
25046
+ const cn = ln(ch);
25047
+ if (cn === "t") {
25048
+ for (const c of textOfT(ch)) chars.push({ ch: c, prId });
25049
+ } else if (OBJ_TAGS.has(cn)) {
25050
+ const sz = findChildByLocalName(ch, "sz");
25051
+ const pos = findChildByLocalName(ch, "pos");
25052
+ objs.push({
25053
+ el: ch,
25054
+ tag: cn,
25055
+ index: chars.length,
25056
+ inline: pos?.getAttribute("treatAsChar") === "1",
25057
+ width: num(sz, "width"),
25058
+ height: num(sz, "height")
25059
+ });
25060
+ }
25061
+ }
25062
+ } else if (tag === "linesegarray") {
25063
+ segs = elements(runEl).filter((s) => ln(s) === "lineseg").map((s) => ({
25064
+ textpos: num(s, "textpos"),
25065
+ vertpos: num(s, "vertpos"),
25066
+ horzpos: num(s, "horzpos"),
25067
+ horzsize: num(s, "horzsize"),
25068
+ textheight: num(s, "textheight", 1e3),
25069
+ baseline: num(s, "baseline", 850)
25070
+ }));
25071
+ }
25072
+ }
25073
+ return { chars, segs, objs, paraPrId: p.getAttribute("paraPrIDRef") };
25074
+ }
25075
+ function charW(c, styles) {
25076
+ const st = (c.prId != null ? styles.charPr.get(c.prId) : void 0) ?? DEFAULT_CHAR;
25077
+ return measureTextWidth(c.ch, st.height, st.ratio, { spacingPct: st.spacing });
25078
+ }
25079
+ function lineNaturalWidth(m, styles, start, end) {
25080
+ let text = 0;
25081
+ for (let i = start; i < end && i < m.chars.length; i++) text += charW(m.chars[i], styles);
25082
+ let obj = 0;
25083
+ for (const o of m.objs) if (o.inline && o.index >= start && o.index < end) obj += o.width;
25084
+ return { text, obj };
25085
+ }
25086
+ function planLines(m, styles) {
25087
+ const align = (m.paraPrId != null ? styles.paraAlign.get(m.paraPrId) : void 0) ?? "JUSTIFY";
25088
+ const plans = [];
25089
+ for (let i = 0; i < m.segs.length; i++) {
25090
+ const seg = m.segs[i];
25091
+ const start = seg.textpos;
25092
+ const end = i + 1 < m.segs.length ? m.segs[i + 1].textpos : Math.max(m.chars.length, start);
25093
+ const nat = lineNaturalWidth(m, styles, start, end);
25094
+ const isLast = i === m.segs.length - 1;
25095
+ let xoff = 0;
25096
+ let scale = 1;
25097
+ const avail = seg.horzsize - nat.obj;
25098
+ if (nat.text > 0 && (!isLast || align === "DISTRIBUTE" || align === "DISTRIBUTE_SPACE")) {
25099
+ scale = avail > 0 ? avail / nat.text : 1;
25100
+ } else if (nat.text + nat.obj > 0 && isLast) {
25101
+ const w = nat.text + nat.obj;
25102
+ if (align === "CENTER") xoff = Math.max(0, (seg.horzsize - w) / 2);
25103
+ else if (align === "RIGHT") xoff = Math.max(0, seg.horzsize - w);
25104
+ }
25105
+ if (!Number.isFinite(scale) || scale <= 0) scale = 1;
25106
+ scale = Math.min(4, Math.max(0.25, scale));
25107
+ plans.push({ seg, xoff, scale, start, end });
25108
+ }
25109
+ return plans;
25110
+ }
25111
+ function advanceTo(m, styles, plan, upto) {
25112
+ let x = 0;
25113
+ for (let i = plan.start; i < upto && i < m.chars.length; i++) x += charW(m.chars[i], styles) * plan.scale;
25114
+ for (const o of m.objs) if (o.inline && o.index >= plan.start && o.index < upto) x += o.width;
25115
+ return x;
25116
+ }
25117
+ function drawPara(p, ox, oy, areaW, ctx, depth) {
25118
+ if (depth > 16) {
25119
+ warnOnce(ctx, "depth", "\uC911\uCCA9 \uAE4A\uC774 16 \uCD08\uACFC \u2014 \uC774\uD558 \uC0DD\uB7B5");
25120
+ return;
25121
+ }
25122
+ const m = buildPara(p);
25123
+ if (m.segs.length === 0) {
25124
+ for (const o of m.objs) drawObject(o, ox, oy, 0, areaW, ctx, depth);
25125
+ return;
25126
+ }
25127
+ const plans = planLines(m, ctx.styles);
25128
+ const baseV = m.segs[0].vertpos;
25129
+ for (const plan of plans) {
25130
+ const { seg } = plan;
25131
+ let i = plan.start;
25132
+ let cursor = ox + seg.horzpos + plan.xoff;
25133
+ const y = oy + seg.vertpos + seg.baseline;
25134
+ while (i < plan.end && i < m.chars.length) {
25135
+ const prId = m.chars[i].prId;
25136
+ let j = i;
25137
+ let piece = "";
25138
+ while (j < plan.end && j < m.chars.length && m.chars[j].prId === prId) {
25139
+ piece += m.chars[j].ch;
25140
+ j++;
25141
+ }
25142
+ for (const o of m.objs) {
25143
+ if (o.inline && o.index > i && o.index < j) {
25144
+ piece = piece.slice(0, o.index - i);
25145
+ j = o.index;
25146
+ break;
25147
+ }
25148
+ }
25149
+ {
25150
+ const cut = piece.search(/ {2,}/);
25151
+ if (cut > 0) {
25152
+ piece = piece.slice(0, cut);
25153
+ j = i + cut;
25154
+ } else if (cut === 0) {
25155
+ const runEnd = piece.match(/^ +/)[0].length;
25156
+ piece = piece.slice(0, runEnd);
25157
+ j = i + runEnd;
25158
+ }
25159
+ }
25160
+ const st = (prId != null ? ctx.styles.charPr.get(prId) : void 0) ?? DEFAULT_CHAR;
25161
+ const w = measureTextWidth(piece, st.height, st.ratio, { spacingPct: st.spacing }) * plan.scale;
25162
+ if (piece.trim().length > 0) {
25163
+ const attrs = [`x="${pt(cursor)}"`, `y="${pt(y)}"`, `font-size="${pt(st.height)}"`];
25164
+ if ([...piece].length > 1 && w > 50) {
25165
+ attrs.push(`textLength="${pt(w)}"`, `lengthAdjust="${plan.scale < 1 ? "spacingAndGlyphs" : "spacing"}"`);
25166
+ }
25167
+ if (st.bold) attrs.push(`font-weight="bold"`);
25168
+ if (st.italic) attrs.push(`font-style="italic"`);
25169
+ if (st.underline) attrs.push(`text-decoration="underline"`);
25170
+ if (st.color) attrs.push(`fill="${escapeXml3(st.color)}"`);
25171
+ ctx.svg.push(`<text ${attrs.join(" ")}>${escapeXml3(piece)}</text>`);
25172
+ ctx.stats.texts++;
25173
+ }
25174
+ cursor += w;
25175
+ for (const o of m.objs) if (o.inline && o.index === j) cursor += o.width;
25176
+ i = j;
25177
+ }
25178
+ }
25179
+ for (const o of m.objs) {
25180
+ if (o.inline) {
25181
+ let plan = plans[0];
25182
+ for (const pl of plans) if (pl.start <= o.index && (o.index < pl.end || pl === plans[plans.length - 1])) plan = pl;
25183
+ const x = ox + plan.seg.horzpos + plan.xoff + advanceTo(m, ctx.styles, plan, o.index);
25184
+ const yTop = oy + plan.seg.vertpos + Math.max(0, plan.seg.baseline - o.height);
25185
+ drawObject(o, x, yTop, baseV, areaW, ctx, depth);
25186
+ } else {
25187
+ const { x, y } = anchorObject(o, ox, oy, baseV, areaW, ctx);
25188
+ drawObject(o, x, y, baseV, areaW, ctx, depth);
25189
+ }
25190
+ }
25191
+ }
25192
+ function anchorObject(o, ox, oy, baseV, areaW, ctx) {
25193
+ const { PW, PH, ML, MT, BODY_W, BODY_H } = ctx.geom;
25194
+ const pos = findChildByLocalName(o.el, "pos");
25195
+ const om = findChildByLocalName(o.el, "outMargin");
25196
+ const omT = num(om, "top"), omB = num(om, "bottom");
25197
+ const w = o.width, h = o.height;
25198
+ if (!pos) return { x: ox, y: oy + baseV };
25199
+ const vo = num(pos, "vertOffset");
25200
+ const ho = num(pos, "horzOffset");
25201
+ const vrel = pos.getAttribute("vertRelTo") ?? "PARA";
25202
+ const hrel = pos.getAttribute("horzRelTo") ?? "PARA";
25203
+ const va = pos.getAttribute("vertAlign") ?? "TOP";
25204
+ const ha = pos.getAttribute("horzAlign") ?? "LEFT";
25205
+ const wrap = o.el.getAttribute("textWrap") ?? "TOP_AND_BOTTOM";
25206
+ let y;
25207
+ if (vrel === "PAPER") {
25208
+ y = va === "BOTTOM" ? PH - h - vo : va === "CENTER" ? (PH - h) / 2 + vo : vo;
25209
+ } else if (vrel === "PAGE") {
25210
+ y = va === "BOTTOM" ? MT + BODY_H - h - vo : va === "CENTER" ? MT + (BODY_H - h) / 2 + vo : MT + vo;
25211
+ } else if (wrap === "TOP_AND_BOTTOM") {
25212
+ const pushed = baseV - (omT + h + omB);
25213
+ const anchor = pushed >= -100 ? pushed : baseV;
25214
+ y = oy + anchor + omT + vo;
25215
+ } else {
25216
+ y = oy + baseV + vo;
25217
+ }
25218
+ let x;
25219
+ if (hrel === "PAGE") {
25220
+ x = ha === "RIGHT" ? ML + BODY_W - w - ho : ha === "CENTER" ? ML + (BODY_W - w) / 2 + ho : ML + ho;
25221
+ } else if (hrel === "PAPER") {
25222
+ x = ha === "RIGHT" ? PW - w - ho : ha === "CENTER" ? (PW - w) / 2 + ho : ho;
25223
+ } else {
25224
+ x = ha === "RIGHT" ? ox + areaW - w - ho : ha === "CENTER" ? ox + (areaW - w) / 2 + ho : ox + ho;
25225
+ }
25226
+ return { x, y };
25227
+ }
25228
+ function drawObject(o, x, y, baseV, areaW, ctx, depth) {
25229
+ if (o.tag === "tbl") drawTable(o.el, x, y, ctx, depth + 1);
25230
+ else if (o.tag === "pic") drawPic(o.el, x, y, ctx);
25231
+ else if (o.tag === "container") {
25232
+ for (const ch of elements(o.el)) {
25233
+ const tag = ln(ch);
25234
+ if (!OBJ_TAGS.has(tag)) continue;
25235
+ const sz = findChildByLocalName(ch, "sz");
25236
+ const off = findChildByLocalName(ch, "offset");
25237
+ const sub = { el: ch, tag, index: 0, inline: true, width: num(sz, "width"), height: num(sz, "height") };
25238
+ drawObject(sub, x + num(off, "x"), y + num(off, "y"), baseV, areaW, ctx, depth + 1);
25239
+ }
25240
+ } else if (o.tag === "equation") {
25241
+ warnOnce(ctx, "equation", "\uC218\uC2DD \uAC1C\uCCB4\uB294 \uB80C\uB354 \uBBF8\uC9C0\uC6D0 \u2014 \uC0DD\uB7B5");
25242
+ } else {
25243
+ warnOnce(ctx, `shape:${o.tag}`, `\uB3C4\uD615 \uAC1C\uCCB4(${o.tag}) \uB80C\uB354 \uBBF8\uC9C0\uC6D0 \u2014 \uC0DD\uB7B5`);
25244
+ }
25245
+ }
25246
+ function cellContentExtent(cell, ctx) {
25247
+ if (!cell.sub) return 0;
25248
+ let ext = 0;
25249
+ for (const p of elements(cell.sub)) {
25250
+ if (ln(p) !== "p") continue;
25251
+ const m = buildPara(p);
25252
+ for (const s of m.segs) ext = Math.max(ext, s.vertpos + s.textheight);
25253
+ const baseV = m.segs[0]?.vertpos ?? 0;
25254
+ for (const o of m.objs) {
25255
+ if (o.inline) continue;
25256
+ const pos = findChildByLocalName(o.el, "pos");
25257
+ if ((pos?.getAttribute("vertRelTo") ?? "PARA") !== "PARA") continue;
25258
+ const om = findChildByLocalName(o.el, "outMargin");
25259
+ const pushed = baseV - (num(om, "top") + o.height + num(om, "bottom"));
25260
+ const anchor = pushed >= -100 ? pushed : baseV;
25261
+ ext = Math.max(ext, anchor + num(om, "top") + num(pos, "vertOffset") + o.height);
25262
+ }
25263
+ }
25264
+ return ext;
25265
+ }
25266
+ function edgeLine(x1, y1, x2, y2, e) {
25267
+ const dash = /DASH|DOT/.test(e.type) ? ` stroke-dasharray="${e.type.includes("DOT") ? "1,1.5" : "3,1.5"}"` : "";
25268
+ return `<line x1="${pt(x1)}" y1="${pt(y1)}" x2="${pt(x2)}" y2="${pt(y2)}" stroke="${escapeXml3(e.color)}" stroke-width="${e.widthPt.toFixed(2)}"${dash}/>`;
25269
+ }
25270
+ function drawTable(tbl, tx, ty, ctx, depth) {
25271
+ if (depth > 16) {
25272
+ warnOnce(ctx, "depth", "\uC911\uCCA9 \uAE4A\uC774 16 \uCD08\uACFC \u2014 \uC774\uD558 \uC0DD\uB7B5");
25273
+ return;
25274
+ }
25275
+ ctx.stats.tables++;
25276
+ const tblSz = findChildByLocalName(tbl, "sz");
25277
+ const inMargin = findChildByLocalName(tbl, "inMargin");
25278
+ const defL = num(inMargin, "left", 141), defR = num(inMargin, "right", 141);
25279
+ const defT = num(inMargin, "top", 141), defB = num(inMargin, "bottom", 141);
25280
+ const cells = [];
25281
+ for (const tr of elements(tbl)) {
25282
+ if (ln(tr) !== "tr") continue;
25283
+ for (const tc of elements(tr)) {
25284
+ if (ln(tc) !== "tc") continue;
25285
+ const addr = findChildByLocalName(tc, "cellAddr");
25286
+ const span = findChildByLocalName(tc, "cellSpan");
25287
+ const csz = findChildByLocalName(tc, "cellSz");
25288
+ const cm = findChildByLocalName(tc, "cellMargin");
25289
+ if (!addr || !csz) continue;
25290
+ cells.push({
25291
+ el: tc,
25292
+ ca: num(addr, "colAddr"),
25293
+ ra: num(addr, "rowAddr"),
25294
+ cs: Math.max(1, num(span, "colSpan", 1)),
25295
+ rs: Math.max(1, num(span, "rowSpan", 1)),
25296
+ w: num(csz, "width"),
25297
+ h: num(csz, "height"),
25298
+ bfId: tc.getAttribute("borderFillIDRef"),
25299
+ sub: findChildByLocalName(tc, "subList"),
25300
+ marginL: cm ? num(cm, "left", defL) : defL,
25301
+ marginR: cm ? num(cm, "right", defR) : defR,
25302
+ marginT: cm ? num(cm, "top", defT) : defT,
25303
+ marginB: cm ? num(cm, "bottom", defB) : defB
25304
+ });
25305
+ }
25306
+ }
25307
+ if (cells.length === 0 || cells.length > 4096) return;
25308
+ const nCols = Math.max(...cells.map((c) => c.ca + c.cs));
25309
+ const nRows = Math.max(...cells.map((c) => c.ra + c.rs));
25310
+ const colCons = cells.map((c) => ({ a: c.ca, b: c.ca + c.cs, size: c.w }));
25311
+ const colX = solveBoundaries(colCons, nCols, num(tblSz, "width") || void 0);
25312
+ const rowH = solveRowHeights(
25313
+ cells.map((c) => ({ rowAddr: c.ra, rowSpan: c.rs, height: c.h, contentH: c.rs === 1 ? cellContentExtent(c, ctx) : void 0 })),
25314
+ nRows
25315
+ );
25316
+ const rowY = [0];
25317
+ for (let r = 0; r < nRows; r++) rowY.push(rowY[r] + rowH[r]);
25318
+ const geom = cells.map((c) => ({
25319
+ c,
25320
+ x: tx + colX[c.ca],
25321
+ y: ty + rowY[c.ra],
25322
+ w: colX[Math.min(c.ca + c.cs, nCols)] - colX[c.ca],
25323
+ h: rowY[Math.min(c.ra + c.rs, nRows)] - rowY[c.ra]
25324
+ }));
25325
+ for (const g of geom) {
25326
+ const bf = g.c.bfId != null ? ctx.styles.borderFill.get(g.c.bfId) : void 0;
25327
+ if (bf?.fill) ctx.svg.push(`<rect x="${pt(g.x)}" y="${pt(g.y)}" width="${pt(g.w)}" height="${pt(g.h)}" fill="${escapeXml3(bf.fill)}"/>`);
25328
+ }
25329
+ for (const g of geom) {
25330
+ const { c } = g;
25331
+ if (!c.sub) continue;
25332
+ const innerH = g.h - c.marginT - c.marginB;
25333
+ const extent = cellContentExtent(c, ctx);
25334
+ const va = c.sub.getAttribute("vertAlign") ?? "TOP";
25335
+ let yoff = 0;
25336
+ if (va === "CENTER") yoff = Math.max(0, (innerH - extent) / 2);
25337
+ else if (va === "BOTTOM") yoff = Math.max(0, innerH - extent);
25338
+ for (const p of elements(c.sub)) {
25339
+ if (ln(p) !== "p") continue;
25340
+ drawPara(p, g.x + c.marginL, g.y + c.marginT + yoff, g.w - c.marginL - c.marginR, ctx, depth + 1);
25341
+ }
25342
+ }
25343
+ for (const g of geom) {
25344
+ const bf = g.c.bfId != null ? ctx.styles.borderFill.get(g.c.bfId) : void 0;
25345
+ if (!bf) continue;
25346
+ if (bf.top) ctx.svg.push(edgeLine(g.x, g.y, g.x + g.w, g.y, bf.top));
25347
+ if (bf.bottom) ctx.svg.push(edgeLine(g.x, g.y + g.h, g.x + g.w, g.y + g.h, bf.bottom));
25348
+ if (bf.left) ctx.svg.push(edgeLine(g.x, g.y, g.x, g.y + g.h, bf.left));
25349
+ if (bf.right) ctx.svg.push(edgeLine(g.x + g.w, g.y, g.x + g.w, g.y + g.h, bf.right));
25350
+ }
25351
+ }
25352
+ function drawPic(pic, x, y, ctx) {
25353
+ const sz = findChildByLocalName(pic, "sz");
25354
+ const w = num(sz, "width", 5669), h = num(sz, "height", 5669);
25355
+ const img = findFirst(pic, "img");
25356
+ const ref = img?.getAttribute("binaryItemIDRef");
25357
+ const loaded = ref != null ? ctx.images.get(ref) : void 0;
25358
+ if (!loaded) {
25359
+ ctx.svg.push(`<rect x="${pt(x)}" y="${pt(y)}" width="${pt(w)}" height="${pt(h)}" fill="#eee" stroke="#c00" stroke-width="0.5"/>`);
25360
+ warnOnce(ctx, `img:${ref}`, `\uC774\uBBF8\uC9C0 \uBC14\uC774\uB108\uB9AC \uB204\uB77D: ${ref ?? "(ref \uC5C6\uC74C)"}`);
25361
+ return;
25362
+ }
25363
+ ctx.stats.images++;
25364
+ const orgSz = findChildByLocalName(pic, "orgSz");
25365
+ const clip = findChildByLocalName(pic, "imgClip");
25366
+ const orgW = num(orgSz, "width"), orgH = num(orgSz, "height");
25367
+ const cl = num(clip, "left"), ct = num(clip, "top");
25368
+ const cr = num(clip, "right", orgW), cb = num(clip, "bottom", orgH);
25369
+ const cropped = orgW > 0 && orgH > 0 && clip != null && (cl > 0 || ct > 0 || cr < orgW || cb < orgH) && cr > cl && cb > ct;
25370
+ if (cropped) {
25371
+ ctx.svg.push(
25372
+ `<svg x="${pt(x)}" y="${pt(y)}" width="${pt(w)}" height="${pt(h)}" viewBox="${pt(cl)} ${pt(ct)} ${pt(cr - cl)} ${pt(cb - ct)}" preserveAspectRatio="none"><image x="0" y="0" width="${pt(orgW)}" height="${pt(orgH)}" preserveAspectRatio="none" href="${loaded.dataUri}"/></svg>`
25373
+ );
25374
+ } else {
25375
+ ctx.svg.push(`<image x="${pt(x)}" y="${pt(y)}" width="${pt(w)}" height="${pt(h)}" preserveAspectRatio="none" href="${loaded.dataUri}"/>`);
25376
+ }
25377
+ }
25378
+ function sniffMime(name, bytes) {
25379
+ const lower = name.toLowerCase();
25380
+ if (lower.endsWith(".png") || bytes.length > 4 && bytes[0] === 137 && bytes[1] === 80) return "image/png";
25381
+ if (lower.endsWith(".bmp") || bytes.length > 2 && bytes[0] === 66 && bytes[1] === 77) return "image/bmp";
25382
+ if (lower.endsWith(".gif")) return "image/gif";
25383
+ if (lower.endsWith(".svg")) return "image/svg+xml";
25384
+ return "image/jpeg";
25385
+ }
25386
+ async function renderHwpxToSvg(input, options) {
25387
+ const maxImg = options?.maxImageBytes ?? 40 * 1024 * 1024;
25388
+ let zip;
25389
+ try {
25390
+ zip = await JSZip10.loadAsync(input);
25391
+ } catch {
25392
+ throw new KordocError("HWPX(ZIP) \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uB80C\uB354\uB294 HWPX\uB9CC \uC9C0\uC6D0");
25393
+ }
25394
+ const secFile = zip.file("Contents/section0.xml") ?? zip.file(/Contents\/section\d+\.xml$/i).sort((a, b) => a.name.localeCompare(b.name))[0];
25395
+ if (!secFile) throw new KordocError("Contents/section0.xml \uC5C6\uC74C \u2014 HWPX\uAC00 \uC544\uB2C8\uAC70\uB098 \uC190\uC0C1\uB428");
25396
+ const secXml = await secFile.async("string");
25397
+ if (secXml.length > MAX_DECOMPRESS_SIZE) throw new KordocError("\uC139\uC158 XML\uC774 \uD5C8\uC6A9 \uD06C\uAE30\uB97C \uCD08\uACFC");
25398
+ if (!secXml.includes("linesegarray")) {
25399
+ throw new KordocError("\uC870\uD310 \uCE90\uC2DC(linesegarray) \uC5C6\uC74C \u2014 \uD55C\uCEF4\uC5D0\uC11C \uC800\uC7A5\uD55C HWPX\uB9CC \uB80C\uB354 \uAC00\uB2A5");
25400
+ }
25401
+ const warnings = [];
25402
+ const headFile = zip.file("Contents/header.xml") ?? zip.file("Contents/head.xml");
25403
+ const styles = headFile ? parseRenderStyles(await headFile.async("string")) : { charPr: /* @__PURE__ */ new Map(), paraAlign: /* @__PURE__ */ new Map(), borderFill: /* @__PURE__ */ new Map() };
25404
+ if (!headFile) warnings.push("header.xml \uC5C6\uC74C \u2014 \uAE30\uBCF8 \uC2A4\uD0C0\uC77C\uB85C \uB80C\uB354");
25405
+ const binmap = /* @__PURE__ */ new Map();
25406
+ const hpf = zip.file(/content\.hpf$/i)[0];
25407
+ if (hpf) {
25408
+ const man = await hpf.async("string");
25409
+ for (const m of man.matchAll(/<[^>]*\bid="([^"]+)"[^>]*\bhref="(BinData\/[^"]+)"[^>]*>/g)) binmap.set(m[1], m[2]);
25410
+ for (const m of man.matchAll(/<[^>]*\bhref="(BinData\/[^"]+)"[^>]*\bid="([^"]+)"[^>]*>/g)) binmap.set(m[2], m[1]);
25411
+ }
25412
+ const images = /* @__PURE__ */ new Map();
25413
+ const refs = /* @__PURE__ */ new Set();
25414
+ for (const m of secXml.matchAll(/binaryItemIDRef="([^"]+)"/g)) refs.add(m[1]);
25415
+ for (const ref of refs) {
25416
+ let href = binmap.get(ref);
25417
+ if (!href) {
25418
+ const cand = zip.file(new RegExp(`BinData/.*${ref.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "i"))[0];
25419
+ href = cand?.name;
25420
+ }
25421
+ if (!href) continue;
25422
+ const f = zip.file(href) ?? zip.file("Contents/" + href);
25423
+ if (!f) continue;
25424
+ const bytes = await f.async("uint8array");
25425
+ if (bytes.length > maxImg) {
25426
+ warnings.push(`\uC774\uBBF8\uC9C0 ${href} ${(bytes.length / 1048576).toFixed(1)}MB \u2014 \uD55C\uB3C4 \uCD08\uACFC\uB85C \uC0DD\uB7B5`);
25427
+ continue;
25428
+ }
25429
+ images.set(ref, { dataUri: `data:${sniffMime(href, bytes)};base64,${Buffer.from(bytes).toString("base64")}` });
25430
+ }
25431
+ const doc = createXmlParser().parseFromString(secXml, "text/xml");
25432
+ const root = doc.documentElement;
25433
+ if (!root) throw new KordocError("\uC139\uC158 XML \uD30C\uC2F1 \uC2E4\uD328");
25434
+ const pagePr = findFirst(root, "pagePr");
25435
+ const margin = pagePr ? findChildByLocalName(pagePr, "margin") : null;
25436
+ const PW = num(pagePr, "width", 59528), PH = num(pagePr, "height", 84188);
25437
+ const ML = num(margin, "left", 8504);
25438
+ const MT = num(margin, "top", 5668) + num(margin, "header", 0);
25439
+ const BODY_H = PH - MT - num(margin, "bottom", 4252) - num(margin, "footer", 0);
25440
+ const BODY_W = PW - ML - num(margin, "right", 8504);
25441
+ const ctx = {
25442
+ svg: [],
25443
+ geom: { PW, PH, ML, MT, BODY_W, BODY_H },
25444
+ styles,
25445
+ images,
25446
+ warnings,
25447
+ warned: /* @__PURE__ */ new Set(),
25448
+ stats: { texts: 0, images: 0, tables: 0 }
25449
+ };
25450
+ for (const p of elements(root)) {
25451
+ if (ln(p) !== "p") continue;
25452
+ const segs = findChildByLocalName(p, "linesegarray");
25453
+ const first = segs ? elements(segs)[0] : null;
25454
+ if (first && num(first, "vertpos") > BODY_H) continue;
25455
+ drawPara(p, ML, MT, BODY_W, ctx, 0);
25456
+ }
25457
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${pt(PW)} ${pt(PH)}" width="${pt(PW)}" height="${pt(PH)}" font-family="'HCR Batang','\uD568\uCD08\uB86C\uBC14\uD0D5','Hancom Batang',AppleMyungjo,'Noto Serif CJK KR',serif" xml:space="preserve">
25458
+ <rect width="100%" height="100%" fill="white"/>
25459
+ ${ctx.svg.join("\n")}
25460
+ </svg>`;
25461
+ return { svg, width: Math.round(PW) / 100, height: Math.round(PH) / 100, warnings, stats: ctx.stats };
25462
+ }
25463
+
24841
25464
  // src/index.ts
24842
25465
  async function parse(input, options) {
24843
25466
  let buffer;
@@ -24925,7 +25548,7 @@ async function parseHwp(buffer, options) {
24925
25548
  async function parsePdf(buffer, options) {
24926
25549
  let parsePdfDocument;
24927
25550
  try {
24928
- const mod = await import("./parser-NCNME2Z6.js");
25551
+ const mod = await import("./parser-DKIA66MN.js");
24929
25552
  parsePdfDocument = mod.parsePdfDocument;
24930
25553
  } catch {
24931
25554
  return {
@@ -25062,6 +25685,7 @@ export {
25062
25685
  patchHwpx,
25063
25686
  patchHwpxBlocks,
25064
25687
  renderHtml,
25688
+ renderHwpxToSvg,
25065
25689
  scanSectionXml,
25066
25690
  simulateWrap,
25067
25691
  simulateWrapKeepWord