kordoc 3.15.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 (45) hide show
  1. package/README.md +20 -0
  2. package/dist/{-EYPKRLMN.js → -H7N62NZU.js} +17 -12
  3. package/dist/{chunk-734GJLXH.js → chunk-5RHRQ7HK.js} +10 -176
  4. package/dist/chunk-5RHRQ7HK.js.map +1 -0
  5. package/dist/{chunk-DMBTOJK4.cjs → chunk-BIP4JAVG.cjs} +2 -2
  6. package/dist/{chunk-DMBTOJK4.cjs.map → chunk-BIP4JAVG.cjs.map} +1 -1
  7. package/dist/chunk-FGL7BH4P.js +1019 -0
  8. package/dist/chunk-FGL7BH4P.js.map +1 -0
  9. package/dist/{chunk-SCFFABCT.js → chunk-IC56KHBL.js} +2 -2
  10. package/dist/chunk-JFNWJFKP.js +185 -0
  11. package/dist/chunk-JFNWJFKP.js.map +1 -0
  12. package/dist/{chunk-Q5ZPWQID.js → chunk-LYL4IL3E.js} +2 -2
  13. package/dist/{chunk-ZRNYYEE6.js → chunk-Q7EGGW3H.js} +2 -2
  14. package/dist/{chunk-Q3IHI3E6.js → chunk-WD5NUUU6.js} +267 -705
  15. package/dist/chunk-WD5NUUU6.js.map +1 -0
  16. package/dist/cli.js +63 -11
  17. package/dist/cli.js.map +1 -1
  18. package/dist/index.cjs +856 -304
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +65 -1
  21. package/dist/index.d.ts +65 -1
  22. package/dist/index.js +682 -130
  23. package/dist/index.js.map +1 -1
  24. package/dist/mcp.js +65 -7
  25. package/dist/mcp.js.map +1 -1
  26. package/dist/{parser-SNBQZO5E.js → parser-5G247XYD.js} +2 -2
  27. package/dist/{parser-O2SD4DFR.cjs → parser-6V7F3GET.cjs} +14 -14
  28. package/dist/{parser-O2SD4DFR.cjs.map → parser-6V7F3GET.cjs.map} +1 -1
  29. package/dist/{parser-76JSTEP3.js → parser-HBHCD7TE.js} +3 -3
  30. package/dist/render-VA4NHROW.js +10 -0
  31. package/dist/seal-UVDRGHEF.js +10 -0
  32. package/dist/seal-UVDRGHEF.js.map +1 -0
  33. package/dist/{watch-LEK5U5P6.js → watch-HIYNOSFD.js} +7 -5
  34. package/dist/{watch-LEK5U5P6.js.map → watch-HIYNOSFD.js.map} +1 -1
  35. package/package.json +1 -1
  36. package/dist/chunk-734GJLXH.js.map +0 -1
  37. package/dist/chunk-Q3IHI3E6.js.map +0 -1
  38. package/dist/render-LDI3LO2P.js +0 -9
  39. /package/dist/{-EYPKRLMN.js.map → -H7N62NZU.js.map} +0 -0
  40. /package/dist/{chunk-SCFFABCT.js.map → chunk-IC56KHBL.js.map} +0 -0
  41. /package/dist/{chunk-Q5ZPWQID.js.map → chunk-LYL4IL3E.js.map} +0 -0
  42. /package/dist/{chunk-ZRNYYEE6.js.map → chunk-Q7EGGW3H.js.map} +0 -0
  43. /package/dist/{parser-SNBQZO5E.js.map → parser-5G247XYD.js.map} +0 -0
  44. /package/dist/{parser-76JSTEP3.js.map → parser-HBHCD7TE.js.map} +0 -0
  45. /package/dist/{render-LDI3LO2P.js.map → render-VA4NHROW.js.map} +0 -0
@@ -1,39 +1,53 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ HEADING_RATIO_H1,
4
+ HEADING_RATIO_H2,
5
+ HEADING_RATIO_H3,
6
+ MAX_COLS,
7
+ MAX_ROWS,
8
+ blocksToMarkdown,
9
+ buildTable,
10
+ convertTableToText,
11
+ flattenLayoutTables,
12
+ mapPuaText
13
+ } from "./chunk-LYL4IL3E.js";
2
14
  import {
3
15
  detectFormat,
4
16
  detectOle2Format,
5
17
  detectZipFormat,
6
18
  parseLenientCfb
7
19
  } from "./chunk-MEPHGCPQ.js";
20
+ import {
21
+ parsePageRange
22
+ } from "./chunk-MOL7MDBG.js";
23
+ import {
24
+ allLinesegRemovalSplices,
25
+ applySplices,
26
+ buildParagraphSplices,
27
+ buildRangeSplices,
28
+ escapeXmlText,
29
+ findElementEnd,
30
+ paraTText,
31
+ paraTextPureT,
32
+ patchZipEntries,
33
+ scanSectionXml
34
+ } from "./chunk-FGL7BH4P.js";
35
+ import {
36
+ SPACE_EM_FIXED,
37
+ charWidthEm1000,
38
+ fitRatioForFewerLines
39
+ } from "./chunk-5RHRQ7HK.js";
8
40
  import {
9
41
  MAX_DECOMPRESS_SIZE,
10
42
  MAX_XML_DEPTH,
11
43
  MAX_ZIP_ENTRIES,
12
- SPACE_EM_FIXED,
13
44
  applyPageText,
14
- charWidthEm1000,
15
45
  clampSpan,
16
46
  createSectionShared,
17
47
  createXmlParser,
18
48
  extractTextFromNode,
19
- findChildByLocalName,
20
- fitRatioForFewerLines
21
- } from "./chunk-734GJLXH.js";
22
- import {
23
- HEADING_RATIO_H1,
24
- HEADING_RATIO_H2,
25
- HEADING_RATIO_H3,
26
- MAX_COLS,
27
- MAX_ROWS,
28
- blocksToMarkdown,
29
- buildTable,
30
- convertTableToText,
31
- flattenLayoutTables,
32
- mapPuaText
33
- } from "./chunk-Q5ZPWQID.js";
34
- import {
35
- parsePageRange
36
- } from "./chunk-MOL7MDBG.js";
49
+ findChildByLocalName
50
+ } from "./chunk-JFNWJFKP.js";
37
51
  import {
38
52
  KordocError,
39
53
  classifyError,
@@ -44,7 +58,7 @@ import {
44
58
  sanitizeHref,
45
59
  stripDtd,
46
60
  toArrayBuffer
47
- } from "./chunk-SCFFABCT.js";
61
+ } from "./chunk-IC56KHBL.js";
48
62
 
49
63
  // src/index.ts
50
64
  import { readFile } from "fs/promises";
@@ -19283,677 +19297,6 @@ function fillInlineFields(text, values, filled, matchedLabels) {
19283
19297
 
19284
19298
  // src/form/filler-hwpx.ts
19285
19299
  import JSZip5 from "jszip";
19286
-
19287
- // src/roundtrip/source-map.ts
19288
- function escapeXmlText(text) {
19289
- return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
19290
- }
19291
- function decodeXmlEntities(text) {
19292
- return text.replace(/&(lt|gt|amp|quot|apos|#x?[0-9a-fA-F]+);/g, (m, ent) => {
19293
- switch (ent) {
19294
- case "lt":
19295
- return "<";
19296
- case "gt":
19297
- return ">";
19298
- case "amp":
19299
- return "&";
19300
- case "quot":
19301
- return '"';
19302
- case "apos":
19303
- return "'";
19304
- }
19305
- try {
19306
- const code = ent[1] === "x" || ent[1] === "X" ? parseInt(ent.slice(2), 16) : parseInt(ent.slice(1), 10);
19307
- if (!isNaN(code) && code >= 0 && code <= 1114111) return String.fromCodePoint(code);
19308
- } catch {
19309
- }
19310
- return m;
19311
- });
19312
- }
19313
- function tContentToText(raw) {
19314
- return decodeXmlEntities(
19315
- raw.replace(/<\/?(?:[A-Za-z0-9_]+:)?(?:tab|fwSpace|hwSpace|br|lineBreak)(?:\s[^>]*)?\/?>/g, " ").replace(/<[^>]*>/g, "")
19316
- );
19317
- }
19318
- var TAG_RE = /<!--[\s\S]*?-->|<!\[CDATA\[[\s\S]*?\]\]>|<\?[\s\S]*?\?>|<!(?:"[^"]*"|'[^']*'|[^>"'])*>|<\/([^\s>]+)\s*>|<([^\s/>!?]+)((?:"[^"]*"|'[^']*'|[^>"'])*?)(\/?)>/g;
19319
- var T_BARRIER = /* @__PURE__ */ new Set([
19320
- "tbl",
19321
- "ctrl",
19322
- "caption",
19323
- "pic",
19324
- "shape",
19325
- "drawingObject",
19326
- "drawText",
19327
- "shapeComment",
19328
- "memogroup",
19329
- "memo",
19330
- "hiddenComment",
19331
- "equation",
19332
- "parameters",
19333
- "subList",
19334
- "p"
19335
- ]);
19336
- var PARA_CONTAINER = /* @__PURE__ */ new Set([
19337
- "tc",
19338
- "ctrl",
19339
- "caption",
19340
- "drawText",
19341
- "pic",
19342
- "shape",
19343
- "drawingObject",
19344
- "memogroup",
19345
- "memo",
19346
- "hiddenComment",
19347
- "footNote",
19348
- "endNote",
19349
- "fn",
19350
- "en"
19351
- // 각주/미주 — 파서는 호스트 블록 footnoteText로만 흡수
19352
- ]);
19353
- var TABLE_BARRIER = /* @__PURE__ */ new Set([
19354
- "tbl",
19355
- "ctrl",
19356
- "caption",
19357
- "memogroup",
19358
- "memo",
19359
- "hiddenComment"
19360
- ]);
19361
- function localOf(qname) {
19362
- const i = qname.indexOf(":");
19363
- return i >= 0 ? qname.slice(i + 1) : qname;
19364
- }
19365
- function prefixOf(qname) {
19366
- const i = qname.indexOf(":");
19367
- return i >= 0 ? qname.slice(0, i) : "";
19368
- }
19369
- function scanSectionXml(xml, sectionIndex) {
19370
- const stack = [];
19371
- const bodyParagraphs = [];
19372
- const tables = [];
19373
- const headerTexts = [];
19374
- const footerTexts = [];
19375
- const excludedParagraphs = [];
19376
- const orphanTables = [];
19377
- const paraStack = [];
19378
- const tableStack = [];
19379
- const rowStack = [];
19380
- const trStartStack = [];
19381
- const cellStack = [];
19382
- let pendingT = null;
19383
- const ctrlSubStack = [];
19384
- const classifyPara = () => {
19385
- let sawDrawText = false;
19386
- for (let i = stack.length - 1; i >= 0; i--) {
19387
- const l = stack[i].local;
19388
- if (l === "tc") return { kind: "cell", inTextbox: sawDrawText };
19389
- if (l === "drawText") {
19390
- sawDrawText = true;
19391
- continue;
19392
- }
19393
- if (PARA_CONTAINER.has(l)) return { kind: "excluded", inTextbox: sawDrawText };
19394
- }
19395
- return sawDrawText ? { kind: "draw", inTextbox: true } : { kind: "body", inTextbox: false };
19396
- };
19397
- const owningPara = () => {
19398
- if (paraStack.length === 0) return null;
19399
- for (let i = stack.length - 1; i >= 0; i--) {
19400
- const l = stack[i].local;
19401
- if (l === "p") return paraStack[paraStack.length - 1];
19402
- if (T_BARRIER.has(l)) return null;
19403
- }
19404
- return null;
19405
- };
19406
- const isTableTopLevel = () => {
19407
- for (let i = stack.length - 1; i >= 0; i--) {
19408
- if (TABLE_BARRIER.has(stack[i].local)) return false;
19409
- }
19410
- return true;
19411
- };
19412
- const currentCtrlSub = () => ctrlSubStack.length > 0 ? ctrlSubStack[ctrlSubStack.length - 1] : null;
19413
- TAG_RE.lastIndex = 0;
19414
- let m;
19415
- while ((m = TAG_RE.exec(xml)) !== null) {
19416
- const [full, closeName, openName, , selfClose] = m;
19417
- if (closeName === void 0 && openName === void 0) continue;
19418
- if (closeName !== void 0) {
19419
- const local2 = localOf(closeName);
19420
- if (local2 === "t" && pendingT) {
19421
- const { para, contentStart: contentStart2 } = pendingT;
19422
- para.tRanges.push({ contentStart: contentStart2, contentEnd: m.index });
19423
- para.text += tContentToText(xml.slice(contentStart2, m.index));
19424
- pendingT = null;
19425
- }
19426
- for (let i = stack.length - 1; i >= 0; i--) {
19427
- if (stack[i].local === local2) {
19428
- stack.length = i;
19429
- break;
19430
- }
19431
- }
19432
- if (local2 === "p") {
19433
- const para = paraStack.pop();
19434
- if (para && para.kind === "excluded") {
19435
- const sub = currentCtrlSub();
19436
- if (sub && para.text.trim()) sub.texts.push(para.text);
19437
- }
19438
- } else if (local2 === "tc") {
19439
- const cell = cellStack.pop();
19440
- const row = rowStack[rowStack.length - 1];
19441
- if (cell && row) row.push(cell);
19442
- } else if (local2 === "tr") {
19443
- const row = rowStack[rowStack.length - 1];
19444
- const table = tableStack[tableStack.length - 1];
19445
- if (row && table && row.length > 0) {
19446
- table.rows.push(row);
19447
- const trStart = trStartStack[trStartStack.length - 1];
19448
- if (trStart >= 0) table.rowRanges.push({ start: trStart, end: m.index + full.length });
19449
- }
19450
- if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
19451
- if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = -1;
19452
- } else if (local2 === "tbl") {
19453
- const table = tableStack.pop();
19454
- rowStack.pop();
19455
- trStartStack.pop();
19456
- if (table) {
19457
- finalizeTable(table);
19458
- if (!table.topLevel) {
19459
- const cell = cellStack[cellStack.length - 1];
19460
- if (cell) cell.tables.push(table);
19461
- else orphanTables.push(table);
19462
- }
19463
- }
19464
- } else if (local2 === "header" || local2 === "footer") {
19465
- const sub = ctrlSubStack[ctrlSubStack.length - 1];
19466
- if (sub) {
19467
- ctrlSubStack.pop();
19468
- const joined = sub.texts.join("\n").trim();
19469
- if (joined) (sub.kind === "header" ? headerTexts : footerTexts).push(joined);
19470
- }
19471
- }
19472
- continue;
19473
- }
19474
- const qname = openName;
19475
- const local = localOf(qname);
19476
- const attrsRaw = m[3] || "";
19477
- const isSelfClose = selfClose === "/";
19478
- const contentStart = m.index + full.length;
19479
- if (isSelfClose) {
19480
- if (local === "t") {
19481
- const para = owningPara();
19482
- if (para) para.tRanges.push({ contentStart: m.index, contentEnd: m.index + full.length, selfClosing: true, prefix: prefixOf(qname) });
19483
- } else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
19484
- if (!pendingT) {
19485
- const para = owningPara();
19486
- if (para) para.text += " ";
19487
- }
19488
- } else if (local === "run" || local === "r") {
19489
- const para = owningPara();
19490
- if (para && !para.selfCloseRun) para.selfCloseRun = { start: m.index, end: m.index + full.length };
19491
- } else if (local === "cellAddr") {
19492
- const cell = cellStack[cellStack.length - 1];
19493
- if (cell && insideCurrentTable(stack, tableStack)) {
19494
- const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
19495
- const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
19496
- if (!isNaN(ca)) cell.colAddr = ca;
19497
- if (!isNaN(ra)) cell.rowAddr = ra;
19498
- cell.addrTagRange = { start: m.index, end: m.index + full.length };
19499
- }
19500
- } else if (local === "cellSpan") {
19501
- const cell = cellStack[cellStack.length - 1];
19502
- if (cell && insideCurrentTable(stack, tableStack)) {
19503
- const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
19504
- const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
19505
- cell.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
19506
- cell.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
19507
- }
19508
- }
19509
- continue;
19510
- }
19511
- if (local === "t") {
19512
- const para = owningPara();
19513
- if (para) pendingT = { para, contentStart };
19514
- stack.push({ local, qname, contentStart });
19515
- continue;
19516
- }
19517
- stack.push({ local, qname, contentStart });
19518
- if (local === "p") {
19519
- const para = {
19520
- sectionIndex,
19521
- kind: "excluded",
19522
- // 분류는 push 직후 스택 기준 (자기 자신 제외)
19523
- start: m.index,
19524
- tRanges: [],
19525
- text: ""
19526
- };
19527
- stack.pop();
19528
- const cls = classifyPara();
19529
- para.kind = cls.kind;
19530
- if (cls.inTextbox) para.inTextbox = true;
19531
- stack.push({ local, qname, contentStart });
19532
- paraStack.push(para);
19533
- if (para.kind === "body" || para.kind === "draw") bodyParagraphs.push(para);
19534
- else if (para.kind === "cell") {
19535
- const cell = cellStack[cellStack.length - 1];
19536
- if (cell) cell.paragraphs.push(para);
19537
- } else if (para.kind === "excluded") {
19538
- excludedParagraphs.push(para);
19539
- }
19540
- } else if (local === "run" || local === "r") {
19541
- const para = owningPara();
19542
- if (para && para.runPrefix === void 0) para.runPrefix = prefixOf(qname);
19543
- } else if (local === "tbl") {
19544
- const table = {
19545
- sectionIndex,
19546
- start: m.index,
19547
- topLevel: false,
19548
- rows: [],
19549
- rowRanges: [],
19550
- cellByAnchor: /* @__PURE__ */ new Map()
19551
- };
19552
- stack.pop();
19553
- table.topLevel = isTableTopLevel();
19554
- stack.push({ local, qname, contentStart });
19555
- tableStack.push(table);
19556
- rowStack.push([]);
19557
- trStartStack.push(-1);
19558
- if (table.topLevel) tables.push(table);
19559
- } else if (local === "tr") {
19560
- if (rowStack.length > 0) rowStack[rowStack.length - 1] = [];
19561
- if (trStartStack.length > 0) trStartStack[trStartStack.length - 1] = m.index;
19562
- } else if (local === "tc") {
19563
- cellStack.push({ colSpan: 1, rowSpan: 1, paragraphs: [], tables: [] });
19564
- } else if (local === "cellAddr" || local === "cellSpan") {
19565
- const cell = cellStack[cellStack.length - 1];
19566
- if (cell && insideCurrentTable(stack, tableStack)) {
19567
- if (local === "cellAddr") {
19568
- const ca = parseInt(getAttr2(attrsRaw, "colAddr") || "", 10);
19569
- const ra = parseInt(getAttr2(attrsRaw, "rowAddr") || "", 10);
19570
- if (!isNaN(ca)) cell.colAddr = ca;
19571
- if (!isNaN(ra)) cell.rowAddr = ra;
19572
- cell.addrTagRange = { start: m.index, end: contentStart };
19573
- } else {
19574
- const cs = parseInt(getAttr2(attrsRaw, "colSpan") || "1", 10);
19575
- const rs = parseInt(getAttr2(attrsRaw, "rowSpan") || "1", 10);
19576
- cell.colSpan = isNaN(cs) || cs < 1 ? 1 : cs;
19577
- cell.rowSpan = isNaN(rs) || rs < 1 ? 1 : rs;
19578
- }
19579
- }
19580
- } else if (local === "header" || local === "footer") {
19581
- if (stack.some((f) => f.local === "ctrl")) {
19582
- ctrlSubStack.push({ kind: local, texts: [] });
19583
- }
19584
- } else if (local === "tab" || local === "fwSpace" || local === "hwSpace" || local === "br" || local === "lineBreak") {
19585
- const para = owningPara();
19586
- if (para) para.text += " ";
19587
- }
19588
- }
19589
- for (const para of bodyParagraphs) fillRunInsertPos(para, xml);
19590
- for (const para of excludedParagraphs) fillRunInsertPos(para, xml);
19591
- const fillTableInsertPos = (table, depth = 0) => {
19592
- if (depth > 16) return;
19593
- for (const row of table.rows) {
19594
- for (const cell of row) {
19595
- for (const para of cell.paragraphs) fillRunInsertPos(para, xml);
19596
- for (const nested of cell.tables) fillTableInsertPos(nested, depth + 1);
19597
- }
19598
- }
19599
- };
19600
- for (const table of tables) fillTableInsertPos(table);
19601
- for (const table of orphanTables) fillTableInsertPos(table);
19602
- return { sectionIndex, xml, bodyParagraphs, tables, headerTexts, footerTexts, excludedParagraphs, orphanTables };
19603
- }
19604
- function getAttr2(attrsRaw, name) {
19605
- const re = new RegExp(`(?:^|\\s)${name}\\s*=\\s*(?:"([^"]*)"|'([^']*)')`);
19606
- const m = attrsRaw.match(re);
19607
- return m ? m[1] ?? m[2] : void 0;
19608
- }
19609
- function insideCurrentTable(stack, tableStack) {
19610
- if (tableStack.length === 0) return false;
19611
- for (let i = stack.length - 1; i >= 0; i--) {
19612
- const l = stack[i].local;
19613
- if (l === "tc") return true;
19614
- if (l === "tbl") return false;
19615
- }
19616
- return false;
19617
- }
19618
- function fillRunInsertPos(para, xml) {
19619
- if (para.tRanges.length > 0) return;
19620
- const pEnd = findElementEnd(xml, para.start);
19621
- if (pEnd < 0) return;
19622
- const slice = xml.slice(para.start, pEnd);
19623
- const runOpen = slice.match(/<((?:[A-Za-z0-9_]+:)?run)(?:\s(?:"[^"]*"|'[^']*'|[^>"'])*?)?(\/?)>/);
19624
- if (!runOpen || runOpen.index === void 0) return;
19625
- if (runOpen[2] === "/") return;
19626
- const qname = runOpen[1];
19627
- const closeIdx = slice.indexOf(`</${qname}>`, runOpen.index);
19628
- if (closeIdx < 0) return;
19629
- para.runInsertPos = para.start + closeIdx;
19630
- para.runPrefix = prefixOf(qname);
19631
- }
19632
- function findElementEnd(xml, start) {
19633
- const open = xml.slice(start).match(/^<([^\s/>!?]+)/);
19634
- if (!open) return -1;
19635
- const qname = open[1];
19636
- const re = new RegExp(`<${qname}(?=[\\s/>])(?:"[^"]*"|'[^']*'|[^>"'])*?(/?)>|</${qname}\\s*>`, "g");
19637
- re.lastIndex = start;
19638
- let depth = 0;
19639
- let mm;
19640
- while ((mm = re.exec(xml)) !== null) {
19641
- if (mm[0].startsWith("</")) {
19642
- depth--;
19643
- if (depth === 0) return mm.index + mm[0].length;
19644
- } else if (mm[1] !== "/") {
19645
- depth++;
19646
- }
19647
- }
19648
- return -1;
19649
- }
19650
- function finalizeTable(table) {
19651
- const hasAddr = table.rows.some((row) => row.some((c) => c.colAddr !== void 0 && c.rowAddr !== void 0));
19652
- if (hasAddr) {
19653
- for (const row of table.rows) {
19654
- for (const cell of row) {
19655
- if (cell.rowAddr !== void 0 && cell.colAddr !== void 0) {
19656
- table.cellByAnchor.set(`${cell.rowAddr},${cell.colAddr}`, cell);
19657
- }
19658
- }
19659
- }
19660
- return;
19661
- }
19662
- const numRows = table.rows.length;
19663
- const occupied = Array.from({ length: numRows }, () => []);
19664
- for (let rowIdx = 0; rowIdx < numRows; rowIdx++) {
19665
- let colIdx = 0;
19666
- for (const cell of table.rows[rowIdx]) {
19667
- while (occupied[rowIdx][colIdx]) colIdx++;
19668
- cell.rowAddr = rowIdx;
19669
- cell.colAddr = colIdx;
19670
- table.cellByAnchor.set(`${rowIdx},${colIdx}`, cell);
19671
- for (let r = rowIdx; r < Math.min(rowIdx + cell.rowSpan, numRows); r++) {
19672
- for (let c = colIdx; c < colIdx + cell.colSpan; c++) {
19673
- occupied[r][c] = true;
19674
- }
19675
- }
19676
- colIdx += cell.colSpan;
19677
- }
19678
- }
19679
- }
19680
- function buildParagraphSplices(para, newText, xml) {
19681
- if (newText && xml) {
19682
- const orig = paraTText(para, xml);
19683
- if (orig && orig.trim() !== "") {
19684
- const lead = orig.match(/^\s*/)[0];
19685
- const trail = orig.match(/\s*$/)[0];
19686
- if ((lead || trail) && newText.trim() !== "") {
19687
- newText = lead + newText.replace(/^\s+|\s+$/g, "") + trail;
19688
- }
19689
- }
19690
- }
19691
- const escaped = escapeXmlText(newText);
19692
- if (para.tRanges.length > 0) {
19693
- const splices = [];
19694
- const first = para.tRanges[0];
19695
- if (first.selfClosing) {
19696
- const prefix = first.prefix ? first.prefix + ":" : "";
19697
- splices.push({ start: first.contentStart, end: first.contentEnd, replacement: `<${prefix}t>${escaped}</${prefix}t>` });
19698
- } else {
19699
- splices.push({ start: first.contentStart, end: first.contentEnd, replacement: escaped });
19700
- }
19701
- for (let i = 1; i < para.tRanges.length; i++) {
19702
- const r = para.tRanges[i];
19703
- if (!r.selfClosing && r.contentStart < r.contentEnd) {
19704
- splices.push({ start: r.contentStart, end: r.contentEnd, replacement: "" });
19705
- }
19706
- }
19707
- return splices;
19708
- }
19709
- if (para.runInsertPos !== void 0) {
19710
- if (!newText) return [];
19711
- const prefix = para.runPrefix ? para.runPrefix + ":" : "";
19712
- return [{ start: para.runInsertPos, end: para.runInsertPos, replacement: `<${prefix}t>${escaped}</${prefix}t>` }];
19713
- }
19714
- if (para.selfCloseRun && xml) {
19715
- if (!newText) return [];
19716
- const { start, end } = para.selfCloseRun;
19717
- const tag = xml.slice(start, end);
19718
- const qm = tag.match(/^<([^\s/>]+)/);
19719
- if (!qm || !tag.endsWith("/>")) return null;
19720
- const qname = qm[1];
19721
- const colon = qname.indexOf(":");
19722
- const prefix = colon >= 0 ? qname.slice(0, colon) + ":" : "";
19723
- const opened = tag.slice(0, tag.length - 2).trimEnd() + ">";
19724
- return [{ start, end, replacement: `${opened}<${prefix}t>${escaped}</${prefix}t></${qname}>` }];
19725
- }
19726
- return newText ? null : [];
19727
- }
19728
- function paraTText(para, xml) {
19729
- let text = "";
19730
- for (const t of para.tRanges) {
19731
- if (t.selfClosing) continue;
19732
- const raw = xml.slice(t.contentStart, t.contentEnd);
19733
- if (/[<&]/.test(raw)) return null;
19734
- text += raw;
19735
- }
19736
- return text;
19737
- }
19738
- function paraTextPureT(para, xml) {
19739
- let len = 0;
19740
- for (const t of para.tRanges) {
19741
- if (t.selfClosing) continue;
19742
- len += tContentToText(xml.slice(t.contentStart, t.contentEnd)).length;
19743
- }
19744
- return len === para.text.length;
19745
- }
19746
- function buildRangeSplices(para, xml, start, end, replacement) {
19747
- if (start < 0 || end < start) return null;
19748
- const segs = [];
19749
- let offset = 0;
19750
- for (const t of para.tRanges) {
19751
- if (t.selfClosing) continue;
19752
- const raw = xml.slice(t.contentStart, t.contentEnd);
19753
- if (/[<&]/.test(raw)) return null;
19754
- segs.push({ contentStart: t.contentStart, from: offset, to: offset + raw.length });
19755
- offset += raw.length;
19756
- }
19757
- if (segs.length === 0 || end > offset) return null;
19758
- const escaped = escapeXmlText(replacement);
19759
- if (start === end) {
19760
- for (const seg of segs) {
19761
- if (start >= seg.from && start <= seg.to) {
19762
- const at = seg.contentStart + (start - seg.from);
19763
- return [{ start: at, end: at, replacement: escaped }];
19764
- }
19765
- }
19766
- return null;
19767
- }
19768
- const splices = [];
19769
- let placed = false;
19770
- for (const seg of segs) {
19771
- if (seg.to <= start || seg.from >= end) continue;
19772
- const localStart = Math.max(seg.from, start) - seg.from;
19773
- const localEnd = Math.min(seg.to, end) - seg.from;
19774
- splices.push({
19775
- start: seg.contentStart + localStart,
19776
- end: seg.contentStart + localEnd,
19777
- replacement: placed ? "" : escaped
19778
- });
19779
- placed = true;
19780
- }
19781
- return placed ? splices : null;
19782
- }
19783
- function allLinesegRemovalSplices(xml) {
19784
- const segRe = /<(\w+:)?linesegarray\b[^>]*?(?:\/>|>[\s\S]*?<\/\1linesegarray>)/g;
19785
- const splices = [];
19786
- let m;
19787
- while ((m = segRe.exec(xml)) !== null) {
19788
- splices.push({ start: m.index, end: m.index + m[0].length, replacement: "" });
19789
- }
19790
- return splices;
19791
- }
19792
- function applySplices(xml, splices) {
19793
- const sorted = [...splices].sort((a, b) => a.start - b.start);
19794
- for (let i = 1; i < sorted.length; i++) {
19795
- if (sorted[i].start < sorted[i - 1].end) {
19796
- throw new Error("\uC18C\uC2A4\uB9F5 splice \uBC94\uC704 \uACB9\uCE68 \u2014 \uB0B4\uBD80 \uC624\uB958");
19797
- }
19798
- }
19799
- let result = xml;
19800
- for (let i = sorted.length - 1; i >= 0; i--) {
19801
- const s = sorted[i];
19802
- result = result.slice(0, s.start) + s.replacement + result.slice(s.end);
19803
- }
19804
- return result;
19805
- }
19806
-
19807
- // src/roundtrip/zip-patch.ts
19808
- import { deflateRawSync } from "zlib";
19809
- var EOCD_SIG = 101010256;
19810
- var CD_SIG = 33639248;
19811
- var LOCAL_SIG = 67324752;
19812
- var ZIP64_EOCD_LOC_SIG = 117853008;
19813
- function copyBytes(buf, start, end) {
19814
- return new Uint8Array(buf.subarray(start, end));
19815
- }
19816
- function parseCentralDirectory(buf) {
19817
- const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
19818
- const minEocd = Math.max(0, buf.length - 22 - 65535);
19819
- let eocdOffset = -1;
19820
- for (let i = buf.length - 22; i >= minEocd; i--) {
19821
- if (view.getUint32(i, true) === EOCD_SIG && i + 22 + view.getUint16(i + 20, true) === buf.length) {
19822
- eocdOffset = i;
19823
- break;
19824
- }
19825
- }
19826
- if (eocdOffset < 0) {
19827
- for (let i = buf.length - 22; i >= minEocd; i--) {
19828
- if (view.getUint32(i, true) !== EOCD_SIG) continue;
19829
- if (i + 22 + view.getUint16(i + 20, true) > buf.length) continue;
19830
- const cand = view.getUint32(i + 16, true);
19831
- if (cand < buf.length - 4 && view.getUint32(cand, true) === CD_SIG) {
19832
- eocdOffset = i;
19833
- break;
19834
- }
19835
- }
19836
- }
19837
- if (eocdOffset < 0) throw new KordocError("ZIP EOCD\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
19838
- const totalEntries = view.getUint16(eocdOffset + 10, true);
19839
- const cdSize = view.getUint32(eocdOffset + 12, true);
19840
- const cdOffset = view.getUint32(eocdOffset + 16, true);
19841
- if (cdOffset === 4294967295 || totalEntries === 65535) throw new KordocError("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19842
- if (eocdOffset >= 20 && view.getUint32(eocdOffset - 20, true) === ZIP64_EOCD_LOC_SIG) {
19843
- throw new KordocError("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19844
- }
19845
- const decoder = new TextDecoder("utf-8");
19846
- const entries = [];
19847
- let pos = cdOffset;
19848
- for (let i = 0; i < totalEntries; i++) {
19849
- if (view.getUint32(pos, true) !== CD_SIG) throw new KordocError("ZIP Central Directory \uC190\uC0C1");
19850
- const flags = view.getUint16(pos + 8, true);
19851
- const method = view.getUint16(pos + 10, true);
19852
- const crc = view.getUint32(pos + 16, true);
19853
- const compSize = view.getUint32(pos + 20, true);
19854
- const uncompSize = view.getUint32(pos + 24, true);
19855
- const nameLen = view.getUint16(pos + 28, true);
19856
- const extraLen = view.getUint16(pos + 30, true);
19857
- const commentLen = view.getUint16(pos + 32, true);
19858
- const localOffset = view.getUint32(pos + 42, true);
19859
- if (compSize === 4294967295 || uncompSize === 4294967295 || localOffset === 4294967295) {
19860
- throw new KordocError("ZIP64\uB294 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
19861
- }
19862
- const name = decoder.decode(buf.subarray(pos + 46, pos + 46 + nameLen));
19863
- const cdEnd = pos + 46 + nameLen + extraLen + commentLen;
19864
- entries.push({ cdStart: pos, cdEnd, name, flags, method, crc, compSize, uncompSize, localOffset });
19865
- pos = cdEnd;
19866
- }
19867
- return { entries, cdOffset, cdSize, eocdOffset };
19868
- }
19869
- var CRC_TABLE = (() => {
19870
- const table = new Uint32Array(256);
19871
- for (let n = 0; n < 256; n++) {
19872
- let c = n;
19873
- for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
19874
- table[n] = c >>> 0;
19875
- }
19876
- return table;
19877
- })();
19878
- function crc32(data) {
19879
- let crc = 4294967295;
19880
- for (let i = 0; i < data.length; i++) {
19881
- crc = CRC_TABLE[(crc ^ data[i]) & 255] ^ crc >>> 8;
19882
- }
19883
- return (crc ^ 4294967295) >>> 0;
19884
- }
19885
- function patchZipEntries(original, replacements) {
19886
- const { entries, cdOffset, eocdOffset } = parseCentralDirectory(original);
19887
- const view = new DataView(original.buffer, original.byteOffset, original.byteLength);
19888
- for (const name of replacements.keys()) {
19889
- if (!entries.some((e) => e.name === name)) throw new KordocError(`ZIP\uC5D0 \uC5C6\uB294 \uC5D4\uD2B8\uB9AC: ${name}`);
19890
- }
19891
- const byLocal = [...entries].sort((a, b) => a.localOffset - b.localOffset);
19892
- const segments = [];
19893
- const newLocalOffset = /* @__PURE__ */ new Map();
19894
- const newMeta = /* @__PURE__ */ new Map();
19895
- let offset = 0;
19896
- for (let i = 0; i < byLocal.length; i++) {
19897
- const e = byLocal[i];
19898
- const segEnd = i + 1 < byLocal.length ? byLocal[i + 1].localOffset : cdOffset;
19899
- newLocalOffset.set(e, offset);
19900
- const newData = replacements.get(e.name);
19901
- if (newData === void 0) {
19902
- const seg = original.subarray(e.localOffset, segEnd);
19903
- segments.push(seg);
19904
- offset += seg.length;
19905
- continue;
19906
- }
19907
- if (view.getUint32(e.localOffset, true) !== LOCAL_SIG) throw new KordocError("ZIP \uB85C\uCEEC \uD5E4\uB354 \uC2DC\uADF8\uB2C8\uCC98 \uBD88\uC77C\uCE58");
19908
- const nameLen = view.getUint16(e.localOffset + 26, true);
19909
- const extraLen = view.getUint16(e.localOffset + 28, true);
19910
- const headerLen = 30 + nameLen + extraLen;
19911
- const header = copyBytes(original, e.localOffset, e.localOffset + headerLen);
19912
- const hview = new DataView(header.buffer, header.byteOffset, header.byteLength);
19913
- const method = e.method;
19914
- const compData = method === 0 ? newData : new Uint8Array(deflateRawSync(newData));
19915
- const crc = crc32(newData);
19916
- const flags = e.flags & ~8;
19917
- hview.setUint16(6, flags, true);
19918
- hview.setUint32(14, crc, true);
19919
- hview.setUint32(18, compData.length, true);
19920
- hview.setUint32(22, newData.length, true);
19921
- segments.push(header, compData);
19922
- offset += headerLen + compData.length;
19923
- newMeta.set(e, { crc, compSize: compData.length, uncompSize: newData.length, flags });
19924
- }
19925
- const newCdOffset = offset;
19926
- for (const e of entries) {
19927
- const cd = copyBytes(original, e.cdStart, e.cdEnd);
19928
- const cview = new DataView(cd.buffer, cd.byteOffset, cd.byteLength);
19929
- cview.setUint32(42, newLocalOffset.get(e), true);
19930
- const meta = newMeta.get(e);
19931
- if (meta) {
19932
- cview.setUint16(8, meta.flags, true);
19933
- cview.setUint32(16, meta.crc, true);
19934
- cview.setUint32(20, meta.compSize, true);
19935
- cview.setUint32(24, meta.uncompSize, true);
19936
- }
19937
- segments.push(cd);
19938
- offset += cd.length;
19939
- }
19940
- const newCdSize = offset - newCdOffset;
19941
- const eocd = copyBytes(original, eocdOffset);
19942
- const eview = new DataView(eocd.buffer, eocd.byteOffset, eocd.byteLength);
19943
- eview.setUint32(12, newCdSize, true);
19944
- eview.setUint32(16, newCdOffset, true);
19945
- segments.push(eocd);
19946
- offset += eocd.length;
19947
- const result = new Uint8Array(offset);
19948
- let pos = 0;
19949
- for (const seg of segments) {
19950
- result.set(seg, pos);
19951
- pos += seg.length;
19952
- }
19953
- return result;
19954
- }
19955
-
19956
- // src/form/filler-hwpx.ts
19957
19300
  async function fillHwpx(hwpxBuffer, values) {
19958
19301
  const u8 = new Uint8Array(hwpxBuffer);
19959
19302
  const zip = await JSZip5.loadAsync(hwpxBuffer);
@@ -20647,12 +19990,14 @@ function generateContainerXml() {
20647
19990
  </ocf:rootfiles>
20648
19991
  </ocf:container>`;
20649
19992
  }
20650
- function generateManifest() {
19993
+ function generateManifest(chartParts = []) {
19994
+ const chartItems = chartParts.map((p, i) => `
19995
+ <opf:item id="chart${i + 1}" href="${p.name}" media-type="application/xml"/>`).join("");
20651
19996
  return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
20652
19997
  <opf:package xmlns:opf="${NS_OPF}" xmlns:hpf="${NS_HPF}" xmlns:hh="${NS_HEAD}">
20653
19998
  <opf:manifest>
20654
19999
  <opf:item id="header" href="Contents/header.xml" media-type="application/xml"/>
20655
- <opf:item id="section0" href="Contents/section0.xml" media-type="application/xml"/>
20000
+ <opf:item id="section0" href="Contents/section0.xml" media-type="application/xml"/>${chartItems}
20656
20001
  </opf:manifest>
20657
20002
  <opf:spine>
20658
20003
  <opf:itemref idref="header" linear="no"/>
@@ -21699,6 +21044,210 @@ function generateEquationParagraph(input, zOrder = 0) {
21699
21044
  return `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${generateEquationXml(script, zOrder)}</hp:run></hp:p>`;
21700
21045
  }
21701
21046
 
21047
+ // src/hwpx/chart-gen.ts
21048
+ var XML_ESC = { "&": "&amp;", "<": "&lt;", ">": "&gt;" };
21049
+ var xmlEscape = (s) => s.replace(/[&<>]/g, (c) => XML_ESC[c]);
21050
+ var CHART_TYPES = {
21051
+ 0: { el: "barChart", dir: "col", grp: "clustered" },
21052
+ 1: { el: "barChart", dir: "col", grp: "stacked", overlap: 100 },
21053
+ 2: { el: "lineChart", grp: "standard", marker: true },
21054
+ 3: { el: "barChart", dir: "bar", grp: "clustered" },
21055
+ 4: { el: "barChart", dir: "bar", grp: "stacked", overlap: 100 },
21056
+ 5: { el: "scatterChart", scatter: true },
21057
+ 6: { el: "pieChart", pie: true },
21058
+ 7: { el: "pieChart", pie: true, explode: true },
21059
+ 8: { el: "doughnutChart", pie: true, hole: 50 },
21060
+ 9: { el: "areaChart", grp: "standard" },
21061
+ 10: { el: "areaChart", grp: "stacked" },
21062
+ 11: { el: "radarChart", radar: true },
21063
+ 12: { el: "bar3DChart", dir: "col", grp: "clustered" },
21064
+ 13: { el: "bar3DChart", dir: "col", grp: "stacked", overlap: 100 },
21065
+ 14: { el: "bar3DChart", dir: "bar", grp: "clustered" },
21066
+ 15: { el: "bar3DChart", dir: "bar", grp: "stacked", overlap: 100 },
21067
+ 16: { el: "pie3DChart", pie: true },
21068
+ 17: { el: "pie3DChart", pie: true, explode: true },
21069
+ 18: { el: "area3DChart", grp: "standard" },
21070
+ 19: { el: "area3DChart", grp: "stacked" }
21071
+ };
21072
+ var CHART_ALIAS = {
21073
+ column: 0,
21074
+ col: 0,
21075
+ \uC138\uB85C\uB9C9\uB300: 0,
21076
+ \uB9C9\uB300: 0,
21077
+ column_stacked: 1,
21078
+ \uC138\uB85C\uB9C9\uB300_\uB204\uC801: 1,
21079
+ line: 2,
21080
+ \uC120: 2,
21081
+ \uAEBE\uC740\uC120: 2,
21082
+ bar: 3,
21083
+ \uAC00\uB85C\uB9C9\uB300: 3,
21084
+ bar_stacked: 4,
21085
+ scatter: 5,
21086
+ \uBD84\uC0B0: 5,
21087
+ pie: 6,
21088
+ \uC6D0: 6,
21089
+ \uD30C\uC774: 6,
21090
+ pie_explode: 7,
21091
+ doughnut: 8,
21092
+ donut: 8,
21093
+ \uB3C4\uB11B: 8,
21094
+ area: 9,
21095
+ \uC601\uC5ED: 9,
21096
+ area_stacked: 10,
21097
+ radar: 11,
21098
+ \uBC29\uC0AC\uD615: 11,
21099
+ bar3d: 12,
21100
+ column3d: 12,
21101
+ pie3d: 16
21102
+ };
21103
+ function chartSpec(t) {
21104
+ if (!t) return CHART_TYPES[0];
21105
+ const key = CHART_ALIAS[t.toLowerCase()] ?? Number(t);
21106
+ return CHART_TYPES[key] ?? CHART_TYPES[0];
21107
+ }
21108
+ var HU_PER_MM = 7200 / 25.4;
21109
+ var RESERVED_KEYS = /* @__PURE__ */ new Set(["type", "cat", "size", "colors", "point_colors", "title"]);
21110
+ function parseChartFence(text) {
21111
+ let type;
21112
+ let cat = null;
21113
+ let widthMm = 32250 / HU_PER_MM;
21114
+ let heightMm = 18750 / HU_PER_MM;
21115
+ let colors = null;
21116
+ let pointColors = null;
21117
+ const series = [];
21118
+ for (const rawLine of text.split("\n")) {
21119
+ const line = rawLine.trim();
21120
+ if (!line || line.startsWith("#")) continue;
21121
+ const colon = line.search(/[::]/);
21122
+ if (colon <= 0) continue;
21123
+ const key = line.slice(0, colon).trim();
21124
+ const value = line.slice(colon + 1).trim();
21125
+ const keyLower = key.toLowerCase();
21126
+ if (keyLower === "type") {
21127
+ type = value;
21128
+ } else if (keyLower === "cat") {
21129
+ cat = value.split(",").map((s) => s.trim()).filter(Boolean);
21130
+ } else if (keyLower === "size") {
21131
+ const m = value.match(/^(\d+(?:\.\d+)?)\s*[x×]\s*(\d+(?:\.\d+)?)$/i);
21132
+ if (m) {
21133
+ widthMm = Number(m[1]);
21134
+ heightMm = Number(m[2]);
21135
+ }
21136
+ } else if (keyLower === "colors") {
21137
+ colors = value.split(",").map((s) => s.trim()).filter(Boolean);
21138
+ } else if (keyLower === "point_colors") {
21139
+ pointColors = value.split(",").map((s) => s.trim()).filter(Boolean);
21140
+ } else if (keyLower === "title") {
21141
+ } else if (!RESERVED_KEYS.has(keyLower)) {
21142
+ const nums = value.split(",").map((s) => Number(s.trim()));
21143
+ if (nums.length > 0 && nums.every((n) => Number.isFinite(n))) {
21144
+ series.push({ name: key, values: nums });
21145
+ }
21146
+ }
21147
+ }
21148
+ if (series.length === 0) return null;
21149
+ const spec = chartSpec(type);
21150
+ const catFinal = cat ?? series[0].values.map((_, i) => `\uD56D\uBAA9 ${i + 1}`);
21151
+ let finalSeries = spec.pie ? [series[0]] : series;
21152
+ finalSeries = finalSeries.map((s) => ({ ...s }));
21153
+ if (spec.pie) {
21154
+ const slice = colors ?? pointColors;
21155
+ if (slice) finalSeries[0].pointColors = slice;
21156
+ } else {
21157
+ if (colors) finalSeries.forEach((s, i) => {
21158
+ s.color = colors[i % colors.length];
21159
+ });
21160
+ if (pointColors && finalSeries[0]) finalSeries[0].pointColors = pointColors;
21161
+ }
21162
+ return {
21163
+ spec,
21164
+ cat: catFinal,
21165
+ series: finalSeries,
21166
+ widthHu: Math.round(widthMm * HU_PER_MM),
21167
+ heightHu: Math.round(heightMm * HU_PER_MM)
21168
+ };
21169
+ }
21170
+ var colLetter = (i) => String.fromCharCode(66 + i);
21171
+ function strCachePts(vals) {
21172
+ return `<c:ptCount val="${vals.length}"/>` + vals.map((v, i) => `<c:pt idx="${i}"><c:v>${xmlEscape(v)}</c:v></c:pt>`).join("");
21173
+ }
21174
+ function numCachePts(vals) {
21175
+ return `<c:formatCode>General</c:formatCode><c:ptCount val="${vals.length}"/>` + vals.map((v, i) => `<c:pt idx="${i}"><c:v>${Number(v) || 0}</c:v></c:pt>`).join("");
21176
+ }
21177
+ function chartColorFill(color) {
21178
+ if (color == null) return null;
21179
+ const c = color.trim();
21180
+ if (/^accent[1-6]$/i.test(c)) return `<a:solidFill><a:schemeClr val="${c.toLowerCase()}"/></a:solidFill>`;
21181
+ const hex = c.replace(/^#/, "").toUpperCase();
21182
+ if (/^[0-9A-F]{6}$/.test(hex)) return `<a:solidFill><a:srgbClr val="${hex}"/></a:solidFill>`;
21183
+ return null;
21184
+ }
21185
+ function serSpPr(color, stroke) {
21186
+ const f = chartColorFill(color);
21187
+ if (!f) return "<c:spPr/>";
21188
+ return stroke ? `<c:spPr><a:ln w="28575" cap="flat" cmpd="sng" algn="ctr">${f}<a:prstDash val="solid"/><a:round/></a:ln></c:spPr>` : `<c:spPr>${f}</c:spPr>`;
21189
+ }
21190
+ function dPtXml(pointColors, pie) {
21191
+ if (!pointColors?.length) return "";
21192
+ return pointColors.map((col, i) => {
21193
+ const f = chartColorFill(col);
21194
+ if (!f) return "";
21195
+ const mid = pie ? '<c:invertIfNegative val="0"/><c:bubble3D val="0"/><c:explosion val="0"/>' : '<c:bubble3D val="0"/>';
21196
+ return `<c:dPt><c:idx val="${i}"/>${mid}<c:spPr>${f}</c:spPr></c:dPt>`;
21197
+ }).join("");
21198
+ }
21199
+ function stdSer(idx, name, cat, values, explode, color, pointColors, stroke, pie) {
21200
+ const cl = colLetter(idx);
21201
+ return `<c:ser><c:idx val="${idx}"/><c:order val="${idx}"/><c:tx><c:strRef><c:f>Sheet1!$${cl}$1</c:f><c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>${xmlEscape(name)}</c:v></c:pt></c:strCache></c:strRef></c:tx>${serSpPr(color, stroke)}<c:invertIfNegative val="0"/>` + (explode ? `<c:explosion val="25"/>` : "") + dPtXml(pointColors, pie) + `<c:cat><c:strRef><c:f>Sheet1!$A$2:$A$${cat.length + 1}</c:f><c:strCache>${strCachePts(cat)}</c:strCache></c:strRef></c:cat><c:val><c:numRef><c:f>Sheet1!$${cl}$2:$${cl}$${values.length + 1}</c:f><c:numCache>${numCachePts(values)}</c:numCache></c:numRef></c:val></c:ser>`;
21202
+ }
21203
+ function scatterSer(idx, name, xvals, yvals) {
21204
+ const cl = colLetter(idx);
21205
+ return `<c:ser><c:idx val="${idx}"/><c:order val="${idx}"/><c:tx><c:strRef><c:f>Sheet1!$${cl}$1</c:f><c:strCache><c:ptCount val="1"/><c:pt idx="0"><c:v>${xmlEscape(name)}</c:v></c:pt></c:strCache></c:strRef></c:tx><c:spPr><a:ln w="28575"><a:noFill/></a:ln></c:spPr><c:marker><c:symbol val="circle"/><c:size val="7"/></c:marker><c:xVal><c:numRef><c:f>Sheet1!$A$2:$A$${xvals.length + 1}</c:f><c:numCache>${numCachePts(xvals)}</c:numCache></c:numRef></c:xVal><c:yVal><c:numRef><c:f>Sheet1!$${cl}$2:$${cl}$${yvals.length + 1}</c:f><c:numCache>${numCachePts(yvals)}</c:numCache></c:numRef></c:yVal></c:ser>`;
21206
+ }
21207
+ function catAxXml(id, pos, cross) {
21208
+ return `<c:catAx><c:axId val="${id}"/><c:scaling><c:orientation val="minMax"/></c:scaling><c:axPos val="${pos}"/><c:crossAx val="${cross}"/><c:delete val="0"/><c:majorTickMark val="out"/><c:minorTickMark val="none"/><c:tickLblPos val="nextTo"/><c:crosses val="autoZero"/><c:auto val="1"/><c:lblAlgn val="ctr"/><c:lblOffset val="100"/><c:noMultiLvlLbl val="0"/></c:catAx>`;
21209
+ }
21210
+ function valAxXml(id, pos, cross) {
21211
+ return `<c:valAx><c:axId val="${id}"/><c:scaling><c:orientation val="minMax"/></c:scaling><c:axPos val="${pos}"/><c:majorGridlines/><c:numFmt formatCode="General" sourceLinked="1"/><c:crossAx val="${cross}"/><c:delete val="0"/><c:majorTickMark val="out"/><c:minorTickMark val="none"/><c:tickLblPos val="nextTo"/><c:crosses val="autoZero"/><c:crossBetween val="between"/></c:valAx>`;
21212
+ }
21213
+ function buildChartSpaceXml(fence) {
21214
+ const { spec, cat, series } = fence;
21215
+ const NS = 'xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart"';
21216
+ const ax1 = "111111111";
21217
+ const ax2 = "222222222";
21218
+ let plot;
21219
+ if (spec.scatter) {
21220
+ const n = Math.max(0, ...series.map((s) => s.values.length));
21221
+ const xs = Array.from({ length: n }, (_, i) => {
21222
+ const c = cat[i];
21223
+ const v = Number(c);
21224
+ return c !== void 0 && c !== "" && Number.isFinite(v) ? v : i + 1;
21225
+ });
21226
+ const sers = series.map((s, i) => scatterSer(i, s.name, xs, s.values)).join("");
21227
+ plot = `<c:scatterChart><c:scatterStyle val="lineMarker"/><c:varyColors val="0"/>${sers}<c:axId val="${ax1}"/><c:axId val="${ax2}"/></c:scatterChart>` + valAxXml(ax1, "b", ax2) + valAxXml(ax2, "l", ax1);
21228
+ } else if (spec.pie) {
21229
+ const s0 = series[0];
21230
+ plot = `<c:${spec.el}><c:varyColors val="1"/>${stdSer(0, s0.name, cat, s0.values, !!spec.explode, s0.color, s0.pointColors, false, true)}<c:firstSliceAng val="0"/>` + (spec.hole != null ? `<c:holeSize val="${spec.hole}"/>` : "") + `</c:${spec.el}>`;
21231
+ } else {
21232
+ const stroke = spec.el === "lineChart" || spec.el === "radarChart" || !!spec.radar;
21233
+ const sers = series.map((s, i) => stdSer(i, s.name, cat, s.values, false, s.color, s.pointColors, stroke, false)).join("");
21234
+ const horiz = spec.dir === "bar";
21235
+ let inner = "";
21236
+ if (spec.dir) inner += `<c:barDir val="${spec.dir}"/>`;
21237
+ if (spec.grp) inner += `<c:grouping val="${spec.grp}"/>`;
21238
+ if (spec.radar) inner += `<c:radarStyle val="standard"/>`;
21239
+ inner += `<c:varyColors val="0"/>${sers}`;
21240
+ if (spec.marker) inner += `<c:marker val="1"/>`;
21241
+ if (spec.el.startsWith("bar")) inner += `<c:gapWidth val="150"/><c:overlap val="${spec.overlap ?? 0}"/>`;
21242
+ inner += `<c:axId val="${ax1}"/><c:axId val="${ax2}"/>`;
21243
+ plot = `<c:${spec.el}>${inner}</c:${spec.el}>` + catAxXml(ax1, horiz ? "l" : "b", ax2) + valAxXml(ax2, horiz ? "b" : "l", ax1);
21244
+ }
21245
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><c:chartSpace ${NS}><c:date1904 val="0"/><c:roundedCorners val="0"/><c:chart><c:autoTitleDeleted val="0"/><c:plotArea><c:layout/>${plot}</c:plotArea><c:legend><c:legendPos val="r"/><c:overlay val="0"/></c:legend><c:plotVisOnly val="1"/><c:dispBlanksAs val="gap"/></c:chart></c:chartSpace>`;
21246
+ }
21247
+ function buildChartElementXml(partName, widthHu, heightHu, id) {
21248
+ return `<hp:chart id="${id}" zOrder="0" numberingType="PICTURE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" chartIDRef="${partName}"><hp:sz width="${widthHu}" widthRelTo="ABSOLUTE" height="${heightHu}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="709" right="709" top="709" bottom="709"/></hp:chart>`;
21249
+ }
21250
+
21702
21251
  // src/hwpx/gen-section.ts
21703
21252
  function generateSecPr(gongmun) {
21704
21253
  const m = gongmun ? {
@@ -21711,7 +21260,7 @@ function generateSecPr(gongmun) {
21711
21260
  } : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
21712
21261
  return `<hp:secPr textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="1" memoShapeIDRef="0" textVerticalWidthHead="0" masterPageCnt="0"><hp:grid lineGrid="0" charGrid="0" wonggojiFormat="0"/><hp:startNum pageStartsOn="BOTH" page="0" pic="0" tbl="0" equation="0"/><hp:visibility hideFirstHeader="0" hideFirstFooter="0" hideFirstMasterPage="0" border="SHOW_ALL" fill="SHOW_ALL" hideFirstPageNum="0" hideFirstEmptyLine="0" showLineNumber="0"/><hp:pagePr landscape="WIDELY" width="59528" height="84188" gutterType="LEFT_ONLY"><hp:margin header="${m.header}" footer="${m.footer}" gutter="0" left="${m.left}" right="${m.right}" top="${m.top}" bottom="${m.bottom}"/></hp:pagePr><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="-1" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="EACH_COLUMN" beneathText="0"/></hp:footNotePr><hp:endNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="14692344" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr></hp:secPr>`;
21713
21262
  }
21714
- function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null) {
21263
+ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null) {
21715
21264
  const paraXmls = [];
21716
21265
  let isFirst = true;
21717
21266
  const orderedCounters = {};
@@ -21742,6 +21291,21 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
21742
21291
  break;
21743
21292
  }
21744
21293
  case "code_block": {
21294
+ if (chartParts !== null && (block.lang || "").toLowerCase() === "chart") {
21295
+ const fence = parseChartFence(block.text || "");
21296
+ if (fence) {
21297
+ const partName = `Chart/chart${chartParts.length + 1}.xml`;
21298
+ chartParts.push({ name: partName, xml: buildChartSpaceXml(fence) });
21299
+ const chartEl = buildChartElementXml(partName, fence.widthHu, fence.heightHu, 91e5 + blockIdx);
21300
+ if (isFirst) {
21301
+ const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
21302
+ paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
21303
+ isFirst = false;
21304
+ }
21305
+ xml = `<hp:p paraPrIDRef="${PARA_NORMAL}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_NORMAL}">${chartEl}</hp:run></hp:p>`;
21306
+ break;
21307
+ }
21308
+ }
21745
21309
  const codeLines = (block.text || "").split("\n");
21746
21310
  xml = codeLines.map((line) => generateParagraph(line || " ", PARA_CODE)).join("\n ");
21747
21311
  break;
@@ -21851,13 +21415,15 @@ async function markdownToHwpx(markdown, options) {
21851
21415
  const blocks = parseMarkdownToBlocks(markdown);
21852
21416
  const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
21853
21417
  const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
21854
- const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit);
21418
+ const chartParts = [];
21419
+ const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts);
21855
21420
  const zip = new JSZip6();
21856
21421
  zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
21857
21422
  zip.file("META-INF/container.xml", generateContainerXml());
21858
- zip.file("Contents/content.hpf", generateManifest());
21423
+ zip.file("Contents/content.hpf", generateManifest(chartParts));
21859
21424
  zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? []));
21860
21425
  zip.file("Contents/section0.xml", sectionXml);
21426
+ for (const part of chartParts) zip.file(part.name, part.xml);
21861
21427
  zip.file("Preview/PrvText.txt", buildPrvText(blocks));
21862
21428
  return await zip.generateAsync({ type: "arraybuffer" });
21863
21429
  }
@@ -22976,7 +22542,7 @@ async function resolveHeaderEntryName(zip) {
22976
22542
  }
22977
22543
 
22978
22544
  // src/roundtrip/hwp5-patch.ts
22979
- import { deflateRawSync as deflateRawSync2 } from "zlib";
22545
+ import { deflateRawSync } from "zlib";
22980
22546
  import { createRequire as createRequire2 } from "module";
22981
22547
 
22982
22548
  // src/roundtrip/ole-surgeon.ts
@@ -23491,7 +23057,7 @@ async function patchHwp(original, editedMarkdown, options) {
23491
23057
  for (let i = 0; i < scans.length; i++) {
23492
23058
  if (scans[i].repl.size === 0 && scans[i].inserts.size === 0) continue;
23493
23059
  const newStream = serializeRecords(scans[i].records, scans[i].repl, scans[i].inserts);
23494
- const content = compressed ? deflateRawSync2(newStream) : newStream;
23060
+ const content = compressed ? deflateRawSync(newStream) : newStream;
23495
23061
  out = replaceOleStream(out, sectionPaths[i], content);
23496
23062
  }
23497
23063
  data = new Uint8Array(out);
@@ -24726,7 +24292,7 @@ async function parseHwp(buffer, options) {
24726
24292
  async function parsePdf(buffer, options) {
24727
24293
  let parsePdfDocument;
24728
24294
  try {
24729
- const mod = await import("./parser-76JSTEP3.js");
24295
+ const mod = await import("./parser-HBHCD7TE.js");
24730
24296
  parsePdfDocument = mod.parsePdfDocument;
24731
24297
  } catch {
24732
24298
  return {
@@ -24827,10 +24393,6 @@ export {
24827
24393
  inferFieldType,
24828
24394
  extractFormSchema,
24829
24395
  fillFormFields,
24830
- scanSectionXml,
24831
- buildParagraphSplices,
24832
- buildRangeSplices,
24833
- applySplices,
24834
24396
  fillHwpx,
24835
24397
  PRESET_ALIAS,
24836
24398
  normalizeGongmunPreset,
@@ -24857,4 +24419,4 @@ export {
24857
24419
  parseHwpml,
24858
24420
  fillForm
24859
24421
  };
24860
- //# sourceMappingURL=chunk-Q3IHI3E6.js.map
24422
+ //# sourceMappingURL=chunk-WD5NUUU6.js.map