kordoc 2.2.1 → 2.2.3

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.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 chrisryugj
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 chrisryugj
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -49,4 +49,4 @@ export {
49
49
  detectFormat,
50
50
  detectZipFormat
51
51
  };
52
- //# sourceMappingURL=chunk-MUAWCQDY.js.map
52
+ //# sourceMappingURL=chunk-5Y2Q3BRW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/detect.ts"],"sourcesContent":["/** 매직 바이트 기반 파일 포맷 감지 */\n\nimport JSZip from \"jszip\"\nimport type { FileType } from \"./types.js\"\n\n/** 매직 바이트 뷰 생성 (복사 없이 view) */\nfunction magicBytes(buffer: ArrayBuffer): Uint8Array {\n return new Uint8Array(buffer, 0, Math.min(4, buffer.byteLength))\n}\n\n/** ZIP 파일 여부: PK\\x03\\x04 */\nexport function isZipFile(buffer: ArrayBuffer): boolean {\n const b = magicBytes(buffer)\n return b[0] === 0x50 && b[1] === 0x4b && b[2] === 0x03 && b[3] === 0x04\n}\n\n/** HWPX (ZIP 기반 한컴 문서): PK\\x03\\x04 — 하위 호환용 */\nexport function isHwpxFile(buffer: ArrayBuffer): boolean {\n return isZipFile(buffer)\n}\n\n/** HWP 5.x (OLE2 바이너리 한컴 문서): \\xD0\\xCF\\x11\\xE0 */\nexport function isOldHwpFile(buffer: ArrayBuffer): boolean {\n const b = magicBytes(buffer)\n return b[0] === 0xd0 && b[1] === 0xcf && b[2] === 0x11 && b[3] === 0xe0\n}\n\n/** PDF 문서: %PDF */\nexport function isPdfFile(buffer: ArrayBuffer): boolean {\n const b = magicBytes(buffer)\n return b[0] === 0x25 && b[1] === 0x50 && b[2] === 0x44 && b[3] === 0x46\n}\n\n/** 동기 포맷 감지 — ZIP은 모두 \"hwpx\"로 반환 (하위 호환) */\nexport function detectFormat(buffer: ArrayBuffer): FileType {\n if (buffer.byteLength < 4) return \"unknown\"\n if (isZipFile(buffer)) return \"hwpx\"\n if (isOldHwpFile(buffer)) return \"hwp\"\n if (isPdfFile(buffer)) return \"pdf\"\n return \"unknown\"\n}\n\n/**\n * ZIP 내부 구조 기반 포맷 세분화.\n * HWPX, XLSX, DOCX 모두 ZIP이므로 내부 파일로 구분.\n */\nexport async function detectZipFormat(buffer: ArrayBuffer): Promise<\"hwpx\" | \"xlsx\" | \"docx\" | \"unknown\"> {\n try {\n const zip = await JSZip.loadAsync(buffer)\n // XLSX: xl/workbook.xml\n if (zip.file(\"xl/workbook.xml\")) return \"xlsx\"\n // DOCX: word/document.xml\n if (zip.file(\"word/document.xml\")) return \"docx\"\n // HWPX: Contents/ 또는 content.hpf 또는 mimetype\n if (zip.file(\"Contents/content.hpf\") || zip.file(\"mimetype\")) return \"hwpx\"\n // 기타 ZIP 내에 section 파일이 있으면 HWPX로 추정\n const hasSection = Object.keys(zip.files).some(f => f.startsWith(\"Contents/\"))\n if (hasSection) return \"hwpx\"\n return \"unknown\"\n } catch {\n return \"unknown\"\n }\n}\n"],"mappings":";;;AAEA,OAAO,WAAW;AAIlB,SAAS,WAAW,QAAiC;AACnD,SAAO,IAAI,WAAW,QAAQ,GAAG,KAAK,IAAI,GAAG,OAAO,UAAU,CAAC;AACjE;AAGO,SAAS,UAAU,QAA8B;AACtD,QAAM,IAAI,WAAW,MAAM;AAC3B,SAAO,EAAE,CAAC,MAAM,MAAQ,EAAE,CAAC,MAAM,MAAQ,EAAE,CAAC,MAAM,KAAQ,EAAE,CAAC,MAAM;AACrE;AAGO,SAAS,WAAW,QAA8B;AACvD,SAAO,UAAU,MAAM;AACzB;AAGO,SAAS,aAAa,QAA8B;AACzD,QAAM,IAAI,WAAW,MAAM;AAC3B,SAAO,EAAE,CAAC,MAAM,OAAQ,EAAE,CAAC,MAAM,OAAQ,EAAE,CAAC,MAAM,MAAQ,EAAE,CAAC,MAAM;AACrE;AAGO,SAAS,UAAU,QAA8B;AACtD,QAAM,IAAI,WAAW,MAAM;AAC3B,SAAO,EAAE,CAAC,MAAM,MAAQ,EAAE,CAAC,MAAM,MAAQ,EAAE,CAAC,MAAM,MAAQ,EAAE,CAAC,MAAM;AACrE;AAGO,SAAS,aAAa,QAA+B;AAC1D,MAAI,OAAO,aAAa,EAAG,QAAO;AAClC,MAAI,UAAU,MAAM,EAAG,QAAO;AAC9B,MAAI,aAAa,MAAM,EAAG,QAAO;AACjC,MAAI,UAAU,MAAM,EAAG,QAAO;AAC9B,SAAO;AACT;AAMA,eAAsB,gBAAgB,QAAoE;AACxG,MAAI;AACF,UAAM,MAAM,MAAM,MAAM,UAAU,MAAM;AAExC,QAAI,IAAI,KAAK,iBAAiB,EAAG,QAAO;AAExC,QAAI,IAAI,KAAK,mBAAmB,EAAG,QAAO;AAE1C,QAAI,IAAI,KAAK,sBAAsB,KAAK,IAAI,KAAK,UAAU,EAAG,QAAO;AAErE,UAAM,aAAa,OAAO,KAAK,IAAI,KAAK,EAAE,KAAK,OAAK,EAAE,WAAW,WAAW,CAAC;AAC7E,QAAI,WAAY,QAAO;AACvB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  detectFormat,
4
4
  detectZipFormat
5
- } from "./chunk-MUAWCQDY.js";
5
+ } from "./chunk-5Y2Q3BRW.js";
6
6
  import {
7
7
  parsePageRange
8
- } from "./chunk-3TBUDJDE.js";
8
+ } from "./chunk-MOL7MDBG.js";
9
9
 
10
10
  // src/utils.ts
11
- var VERSION = true ? "2.2.1" : "0.0.0-dev";
11
+ var VERSION = true ? "2.2.3" : "0.0.0-dev";
12
12
  function toArrayBuffer(buf) {
13
13
  if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
14
14
  return buf.buffer;
@@ -330,9 +330,47 @@ function blocksToMarkdown(blocks) {
330
330
  }
331
331
  return lines.join("\n").trim();
332
332
  }
333
+ function hasMergedCells(table) {
334
+ for (const row of table.cells) {
335
+ for (const cell of row) {
336
+ if (cell.colSpan > 1 || cell.rowSpan > 1) return true;
337
+ }
338
+ }
339
+ return false;
340
+ }
341
+ function tableToHtml(table) {
342
+ const { cells, rows: numRows, cols: numCols } = table;
343
+ const skip = /* @__PURE__ */ new Set();
344
+ const lines = ["<table>"];
345
+ for (let r = 0; r < numRows; r++) {
346
+ const tag = r === 0 ? "th" : "td";
347
+ const rowHtml = [];
348
+ for (let c = 0; c < numCols; c++) {
349
+ if (skip.has(`${r},${c}`)) continue;
350
+ const cell = cells[r]?.[c];
351
+ if (!cell) continue;
352
+ for (let dr = 0; dr < cell.rowSpan; dr++) {
353
+ for (let dc = 0; dc < cell.colSpan; dc++) {
354
+ if (dr === 0 && dc === 0) continue;
355
+ if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
356
+ }
357
+ }
358
+ const text = sanitizeText(cell.text).replace(/\n/g, "<br>");
359
+ const attrs = [];
360
+ if (cell.colSpan > 1) attrs.push(`colspan="${cell.colSpan}"`);
361
+ if (cell.rowSpan > 1) attrs.push(`rowspan="${cell.rowSpan}"`);
362
+ const attrStr = attrs.length ? " " + attrs.join(" ") : "";
363
+ rowHtml.push(`<${tag}${attrStr}>${text}</${tag}>`);
364
+ }
365
+ if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
366
+ }
367
+ lines.push("</table>");
368
+ return lines.join("\n");
369
+ }
333
370
  function tableToMarkdown(table) {
334
371
  if (table.rows === 0 || table.cols === 0) return "";
335
372
  const { cells, rows: numRows, cols: numCols } = table;
373
+ if (hasMergedCells(table)) return tableToHtml(table);
336
374
  if (numRows === 1 && numCols === 1) {
337
375
  const content = sanitizeText(cells[0][0].text);
338
376
  if (!content) return "";
@@ -5368,7 +5406,7 @@ async function parseXlsxDocument(buffer, options) {
5368
5406
  }
5369
5407
  let pageFilter = null;
5370
5408
  if (options?.pages) {
5371
- const { parsePageRange: parsePageRange2 } = await import("./page-range-OF5I4PQY.js");
5409
+ const { parsePageRange: parsePageRange2 } = await import("./page-range-737B4EZW.js");
5372
5410
  pageFilter = parsePageRange2(options.pages, sheets.length);
5373
5411
  }
5374
5412
  const blocks = [];
@@ -6260,4 +6298,4 @@ export {
6260
6298
  extractFormFields,
6261
6299
  parse
6262
6300
  };
6263
- //# sourceMappingURL=chunk-FINXMRCH.js.map
6301
+ //# sourceMappingURL=chunk-AIG7SDWU.js.map