@clazic/kordoc 2.1.4 → 2.1.6

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/dist/index.js CHANGED
@@ -137,7 +137,7 @@ import JSZip2 from "jszip";
137
137
  import { DOMParser } from "@xmldom/xmldom";
138
138
 
139
139
  // src/utils.ts
140
- var VERSION = true ? "2.1.4" : "0.0.0-dev";
140
+ var VERSION = true ? "2.1.6" : "0.0.0-dev";
141
141
  function toArrayBuffer(buf) {
142
142
  if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) {
143
143
  return buf.buffer;
@@ -5599,7 +5599,7 @@ var HEADER_XML = `<?xml version='1.0' encoding='UTF-8'?>
5599
5599
  <hh:diagonal type="SOLID" width="0.1 mm" color="#000000"/>
5600
5600
  </hh:borderFill>
5601
5601
  </hh:borderFills>
5602
- <hh:charProperties itemCnt="13">
5602
+ <hh:charProperties itemCnt="15">
5603
5603
  <hh:charPr id="0" height="1000" textColor="#000000" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="2">
5604
5604
  <hh:fontRef hangul="1" latin="1" hanja="1" japanese="1" other="1" symbol="1" user="1"/>
5605
5605
  <hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
@@ -5750,6 +5750,30 @@ var HEADER_XML = `<?xml version='1.0' encoding='UTF-8'?>
5750
5750
  <hh:outline type="NONE"/>
5751
5751
  <hh:shadow type="NONE" color="#C0C0C0" offsetX="10" offsetY="10"/>
5752
5752
  </hh:charPr>
5753
+ <hh:charPr id="13" height="1000" textColor="#000000" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="2">
5754
+ <hh:fontRef hangul="1" latin="1" hanja="1" japanese="1" other="1" symbol="1" user="1"/>
5755
+ <hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
5756
+ <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
5757
+ <hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
5758
+ <hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
5759
+ <hh:bold/>
5760
+ <hh:italic/>
5761
+ <hh:underline type="NONE" shape="SOLID" color="#000000"/>
5762
+ <hh:strikeout shape="NONE" color="#000000"/>
5763
+ <hh:outline type="NONE"/>
5764
+ <hh:shadow type="NONE" color="#C0C0C0" offsetX="10" offsetY="10"/>
5765
+ </hh:charPr>
5766
+ <hh:charPr id="14" height="900" textColor="#333333" shadeColor="#F0F0F0" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="2">
5767
+ <hh:fontRef hangul="1" latin="1" hanja="1" japanese="1" other="1" symbol="1" user="1"/>
5768
+ <hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
5769
+ <hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
5770
+ <hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
5771
+ <hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
5772
+ <hh:underline type="NONE" shape="SOLID" color="#000000"/>
5773
+ <hh:strikeout shape="NONE" color="#000000"/>
5774
+ <hh:outline type="NONE"/>
5775
+ <hh:shadow type="NONE" color="#C0C0C0" offsetX="10" offsetY="10"/>
5776
+ </hh:charPr>
5753
5777
  </hh:charProperties>
5754
5778
  <hh:tabProperties itemCnt="3">
5755
5779
  <hh:tabPr id="0" autoTabLeft="0" autoTabRight="0"/>
@@ -6672,6 +6696,8 @@ var CHAR_H3 = "9";
6672
6696
  var CHAR_H456 = "10";
6673
6697
  var CHAR_BOLD = "11";
6674
6698
  var CHAR_ITALIC = "12";
6699
+ var CHAR_BOLD_ITALIC = "13";
6700
+ var CHAR_CODE = "14";
6675
6701
  var PARA_NORMAL = "0";
6676
6702
  var SEC_NS = [
6677
6703
  `xmlns:ha="http://www.hancom.co.kr/hwpml/2011/app"`,
@@ -6699,7 +6725,7 @@ function escapeXml(text) {
6699
6725
  }
6700
6726
  function parseInlineRuns(text) {
6701
6727
  const runs = [];
6702
- const re = /\*\*\*(.+?)\*\*\*|\*\*(.+?)\*\*|\*(.+?)\*|_(.+?)_|`(.+?)`/g;
6728
+ const re = /\*\*\*(.+?)\*\*\*|\*\*(.+?)\*\*|\*(.+?)\*|_(.+?)_|`(.+?)`|\[([^\]]+)\]\(([^)]+)\)/g;
6703
6729
  let last = 0;
6704
6730
  let m;
6705
6731
  while ((m = re.exec(text)) !== null) {
@@ -6708,13 +6734,16 @@ function parseInlineRuns(text) {
6708
6734
  else if (m[2]) runs.push({ text: m[2], bold: true });
6709
6735
  else if (m[3]) runs.push({ text: m[3], italic: true });
6710
6736
  else if (m[4]) runs.push({ text: m[4], italic: true });
6711
- else if (m[5]) runs.push({ text: m[5] });
6737
+ else if (m[5]) runs.push({ text: m[5], code: true });
6738
+ else if (m[6]) runs.push({ text: m[6], url: m[7] });
6712
6739
  last = m.index + m[0].length;
6713
6740
  }
6714
6741
  if (last < text.length) runs.push({ text: text.slice(last) });
6715
6742
  return runs.filter((r) => r.text.length > 0);
6716
6743
  }
6717
6744
  function charPrForRun(run) {
6745
+ if (run.code) return CHAR_CODE;
6746
+ if (run.bold && run.italic) return CHAR_BOLD_ITALIC;
6718
6747
  if (run.bold) return CHAR_BOLD;
6719
6748
  if (run.italic) return CHAR_ITALIC;
6720
6749
  return CHAR_NORMAL;
@@ -6722,19 +6751,41 @@ function charPrForRun(run) {
6722
6751
  function makeRun(text, charPrId) {
6723
6752
  return `<hp:run charPrIDRef="${charPrId}"><hp:t${text ? `>${escapeXml(text)}</hp:t` : "/"}></hp:run>`;
6724
6753
  }
6725
- function makeRunsFromText(text, defaultCharPr) {
6754
+ function makeHyperlinkRun(text, url, charPrId, nextId) {
6755
+ const subId = nextId();
6756
+ const paraId = nextId();
6757
+ return [
6758
+ `<hp:run charPrIDRef="${charPrId}">`,
6759
+ ` <hp:ctrl>`,
6760
+ ` <hp:hyperLink url="${escapeXml(url)}" macro="" visitedStyle="UNKNOWN" visitedStyleIDRef="4294967295">`,
6761
+ ` <hp:subList id="${subId}" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP"`,
6762
+ ` linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0"`,
6763
+ ` hasTextRef="0" hasNumRef="0">`,
6764
+ ` <hp:p id="${paraId}" paraPrIDRef="0" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0">`,
6765
+ ` <hp:run charPrIDRef="${charPrId}"><hp:t>${escapeXml(text)}</hp:t></hp:run>`,
6766
+ ` </hp:p>`,
6767
+ ` </hp:subList>`,
6768
+ ` </hp:hyperLink>`,
6769
+ ` </hp:ctrl>`,
6770
+ `</hp:run>`
6771
+ ].join("\n");
6772
+ }
6773
+ function makeRunsFromText(text, defaultCharPr, nextId) {
6726
6774
  const runs = parseInlineRuns(text);
6727
6775
  if (runs.length === 0) return makeRun("", defaultCharPr);
6728
- if (runs.length === 1 && !runs[0].bold && !runs[0].italic)
6729
- return makeRun(runs[0].text, defaultCharPr);
6730
- return runs.map((r) => makeRun(r.text, charPrForRun(r))).join("");
6776
+ const isPlain = runs.length === 1 && !runs[0].bold && !runs[0].italic && !runs[0].code && !runs[0].url;
6777
+ if (isPlain) return makeRun(runs[0].text, defaultCharPr);
6778
+ return runs.map((r) => {
6779
+ if (r.url && nextId) return makeHyperlinkRun(r.text, r.url, CHAR_NORMAL, nextId);
6780
+ return makeRun(r.text, charPrForRun(r));
6781
+ }).join("");
6731
6782
  }
6732
6783
  var LINESEG = ` <hp:linesegarray>
6733
6784
  <hp:lineseg textpos="0" vertpos="0" vertsize="1000" textheight="1000" baseline="850" spacing="600" horzpos="0" horzsize="42520" flags="393216"/>
6734
6785
  </hp:linesegarray>`;
6735
6786
  function makeParagraph(text, charPrId, paraPrId, nextId) {
6736
6787
  const id = nextId();
6737
- const runs = makeRunsFromText(text, charPrId);
6788
+ const runs = makeRunsFromText(text, charPrId, nextId);
6738
6789
  return [
6739
6790
  `<hp:p id="${id}" paraPrIDRef="${paraPrId}" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0">`,
6740
6791
  ` ${runs}`,
@@ -6820,6 +6871,15 @@ ${row.map((cell, colIdx) => makeTableCell(cell, colIdx, rowIdx, colWidth, rowIdx
6820
6871
  `</hp:p>`
6821
6872
  ].join("\n");
6822
6873
  }
6874
+ function getIndent(line) {
6875
+ let spaces = 0;
6876
+ for (const ch of line) {
6877
+ if (ch === " ") spaces++;
6878
+ else if (ch === " ") spaces += 2;
6879
+ else break;
6880
+ }
6881
+ return Math.floor(spaces / 2);
6882
+ }
6823
6883
  function parseMarkdownToBlocks(md) {
6824
6884
  const lines = md.split("\n");
6825
6885
  const blocks = [];
@@ -6838,6 +6898,12 @@ function parseMarkdownToBlocks(md) {
6838
6898
  i++;
6839
6899
  continue;
6840
6900
  }
6901
+ const imgm = trimmed.match(/^!\[([^\]]*)\]\(([^)]+)\)$/);
6902
+ if (imgm) {
6903
+ blocks.push({ type: "image", alt: imgm[1], src: imgm[2] });
6904
+ i++;
6905
+ continue;
6906
+ }
6841
6907
  if (trimmed.startsWith("|")) {
6842
6908
  const tableRows = [];
6843
6909
  while (i < lines.length && lines[i].trim().startsWith("|")) {
@@ -6853,35 +6919,84 @@ function parseMarkdownToBlocks(md) {
6853
6919
  if (tableRows.length > 0) blocks.push({ type: "table", rows: tableRows });
6854
6920
  continue;
6855
6921
  }
6856
- if (/^[-*+]\s/.test(trimmed)) {
6922
+ if (/^\s*[-*+]\s/.test(line)) {
6857
6923
  const items = [];
6858
- while (i < lines.length && /^\s*[-*+]\s/.test(lines[i]))
6859
- items.push(lines[i++].trim().replace(/^[-*+]\s+/, ""));
6924
+ while (i < lines.length && /^\s*[-*+]\s/.test(lines[i])) {
6925
+ const indent = getIndent(lines[i]);
6926
+ const text = lines[i].trim().replace(/^[-*+]\s+/, "");
6927
+ items.push({ text, indent });
6928
+ i++;
6929
+ }
6860
6930
  blocks.push({ type: "list", listType: "unordered", items });
6861
6931
  continue;
6862
6932
  }
6863
- if (/^\d+\.\s/.test(trimmed)) {
6933
+ if (/^\s*\d+\.\s/.test(line)) {
6864
6934
  const items = [];
6865
- while (i < lines.length && /^\s*\d+\.\s/.test(lines[i]))
6866
- items.push(lines[i++].trim().replace(/^\d+\.\s+/, ""));
6935
+ while (i < lines.length && /^\s*\d+\.\s/.test(lines[i])) {
6936
+ const indent = getIndent(lines[i]);
6937
+ const text = lines[i].trim().replace(/^\d+\.\s+/, "");
6938
+ items.push({ text, indent });
6939
+ i++;
6940
+ }
6867
6941
  blocks.push({ type: "list", listType: "ordered", items });
6868
6942
  continue;
6869
6943
  }
6870
6944
  if (trimmed.startsWith("```")) {
6945
+ const lang = trimmed.slice(3).trim();
6871
6946
  i++;
6872
6947
  const codeLines = [];
6873
6948
  while (i < lines.length && !lines[i].trim().startsWith("```")) codeLines.push(lines[i++]);
6874
6949
  if (i < lines.length) i++;
6875
- if (codeLines.length > 0) blocks.push({ type: "paragraph", text: codeLines.join("\n") });
6950
+ if (codeLines.length > 0) blocks.push({ type: "code", text: codeLines.join("\n"), lang });
6876
6951
  continue;
6877
6952
  }
6878
6953
  const paraLines = [];
6879
- while (i < lines.length && lines[i].trim() && !lines[i].trim().startsWith("#") && !lines[i].trim().startsWith("|") && !/^\s*[-*+]\s/.test(lines[i]) && !/^\s*\d+\.\s/.test(lines[i]) && !lines[i].trim().startsWith("```")) paraLines.push(lines[i++].trim());
6954
+ while (i < lines.length && lines[i].trim() && !lines[i].trim().startsWith("#") && !lines[i].trim().startsWith("|") && !/^\s*[-*+]\s/.test(lines[i]) && !/^\s*\d+\.\s/.test(lines[i]) && !lines[i].trim().startsWith("```") && !lines[i].trim().match(/^!\[[^\]]*\]\([^)]+\)$/)) paraLines.push(lines[i++].trim());
6880
6955
  if (paraLines.length > 0) blocks.push({ type: "paragraph", text: paraLines.join(" ") });
6881
6956
  }
6882
6957
  return blocks;
6883
6958
  }
6884
- function generateSectionXml(blocks, styleMap) {
6959
+ function mimeToFormat(mimeType) {
6960
+ if (mimeType.includes("jpeg") || mimeType.includes("jpg")) return "JPG";
6961
+ if (mimeType.includes("gif")) return "GIF";
6962
+ if (mimeType.includes("bmp")) return "BMP";
6963
+ return "PNG";
6964
+ }
6965
+ function makeImageParagraph(binDataId, nextId, widthHwp = 28346, heightHwp = 19843) {
6966
+ const paraId = nextId();
6967
+ return [
6968
+ `<hp:p id="${paraId}" paraPrIDRef="0" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0">`,
6969
+ ` <hp:run charPrIDRef="0">`,
6970
+ ` <hp:pic name="" zOrder="0" numberingType="NONE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES"`,
6971
+ ` lock="0" dropcapstyle="None" pageBreak="CELL">`,
6972
+ ` <hp:instSz width="${widthHwp}" height="${heightHwp}" widthRelTo="ABSOLUTE" heightRelTo="ABSOLUTE" protect="0"/>`,
6973
+ ` <hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0"`,
6974
+ ` holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="COLUMN"`,
6975
+ ` vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/>`,
6976
+ ` <hp:outMargin left="0" right="0" top="0" bottom="0"/>`,
6977
+ ` <hp:content binaryItemIDRef="${binDataId}"/>`,
6978
+ ` <hp:imgRect left="0" top="0" right="${widthHwp}" bottom="${heightHwp}"/>`,
6979
+ ` <hp:imgClip left="0" top="0" right="${widthHwp}" bottom="${heightHwp}"/>`,
6980
+ ` </hp:pic>`,
6981
+ ` </hp:run>`,
6982
+ LINESEG,
6983
+ `</hp:p>`
6984
+ ].join("\n");
6985
+ }
6986
+ function makeCodeParagraphs(code, nextId) {
6987
+ const lines = code.split("\n");
6988
+ return lines.map((line) => {
6989
+ const id = nextId();
6990
+ const safe = escapeXml(line || " ");
6991
+ return [
6992
+ `<hp:p id="${id}" paraPrIDRef="0" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0">`,
6993
+ ` <hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${safe}</hp:t></hp:run>`,
6994
+ LINESEG,
6995
+ `</hp:p>`
6996
+ ].join("\n");
6997
+ }).join("\n");
6998
+ }
6999
+ function generateSectionXml(blocks, styleMap, imageMap) {
6885
7000
  const nextId = makeIdGen();
6886
7001
  const firstId = nextId();
6887
7002
  const defaultCharPr = styleMap ? styleMap.body.charPr : CHAR_NORMAL;
@@ -6930,11 +7045,12 @@ function generateSectionXml(blocks, styleMap) {
6930
7045
  `</hp:p>`
6931
7046
  ].join("\n");
6932
7047
  const bodyParts = [];
7048
+ const orderedCounters = /* @__PURE__ */ new Map();
6933
7049
  for (const block of blocks) {
7050
+ if (block.type !== "list") orderedCounters.clear();
6934
7051
  switch (block.type) {
6935
7052
  case "heading": {
6936
7053
  const level = block.level || 1;
6937
- const headingKey = `h${level}`;
6938
7054
  let charPrId;
6939
7055
  let paraPrId;
6940
7056
  if (styleMap) {
@@ -6959,21 +7075,51 @@ function generateSectionXml(blocks, styleMap) {
6959
7075
  }
6960
7076
  break;
6961
7077
  }
7078
+ case "code": {
7079
+ bodyParts.push(makeCodeParagraphs(block.text || "", nextId));
7080
+ break;
7081
+ }
6962
7082
  case "empty":
6963
7083
  bodyParts.push(makeEmptyParagraph(nextId));
6964
7084
  break;
6965
7085
  case "list": {
6966
7086
  const charPrId = styleMap ? styleMap.body.charPr : CHAR_NORMAL;
6967
7087
  const paraPrId = styleMap ? styleMap.body.paraPr : PARA_NORMAL;
6968
- for (let idx = 0; idx < (block.items || []).length; idx++) {
6969
- const prefix = block.listType === "ordered" ? `${idx + 1}. ` : "\u2022 ";
6970
- bodyParts.push(makeParagraph(prefix + (block.items || [])[idx], charPrId, paraPrId, nextId));
7088
+ const items = block.items || [];
7089
+ if (block.listType === "ordered") {
7090
+ for (const item of items) {
7091
+ const cnt = (orderedCounters.get(item.indent) || 0) + 1;
7092
+ orderedCounters.set(item.indent, cnt);
7093
+ for (const [k] of orderedCounters) {
7094
+ if (k > item.indent) orderedCounters.set(k, 0);
7095
+ }
7096
+ const indent = " ".repeat(item.indent);
7097
+ bodyParts.push(makeParagraph(`${indent}${cnt}. ${item.text}`, charPrId, paraPrId, nextId));
7098
+ }
7099
+ } else {
7100
+ for (const item of items) {
7101
+ const bullets = ["\u2022", "\u25E6", "\u25AA"];
7102
+ const bullet = bullets[Math.min(item.indent, bullets.length - 1)];
7103
+ const indent = " ".repeat(item.indent);
7104
+ bodyParts.push(makeParagraph(`${indent}${bullet} ${item.text}`, charPrId, paraPrId, nextId));
7105
+ }
6971
7106
  }
6972
7107
  break;
6973
7108
  }
6974
7109
  case "table":
6975
7110
  if (block.rows?.length) bodyParts.push(makeTable(block.rows, nextId, styleMap));
6976
7111
  break;
7112
+ case "image": {
7113
+ const src = block.src || "";
7114
+ const binId = imageMap?.get(src);
7115
+ if (binId !== void 0) {
7116
+ bodyParts.push(makeImageParagraph(binId, nextId));
7117
+ } else {
7118
+ const alt = block.alt || src || "(\uC774\uBBF8\uC9C0)";
7119
+ bodyParts.push(makeParagraph(`[\uC774\uBBF8\uC9C0: ${alt}]`, CHAR_NORMAL, PARA_NORMAL, nextId));
7120
+ }
7121
+ break;
7122
+ }
6977
7123
  }
6978
7124
  }
6979
7125
  return [
@@ -7010,9 +7156,28 @@ async function markdownToHwpx(markdown, options) {
7010
7156
  warnings.push(`[warn] \uD15C\uD50C\uB9BF \uCC98\uB9AC \uC2E4\uD328: ${msg}. \uAE30\uBCF8 \uC2A4\uD0C0\uC77C \uC0AC\uC6A9`);
7011
7157
  }
7012
7158
  }
7159
+ const imageMap = /* @__PURE__ */ new Map();
7160
+ const binDataEntries = [];
7161
+ if (opts.images && opts.images.length > 0) {
7162
+ for (let idx = 0; idx < opts.images.length; idx++) {
7163
+ const img = opts.images[idx];
7164
+ const binId = idx + 1;
7165
+ const format = mimeToFormat(img.mimeType);
7166
+ const nameWithoutExt = img.filename.replace(/\.[^.]+$/, "");
7167
+ const binFilename = `BinData/${nameWithoutExt}`;
7168
+ imageMap.set(img.filename, binId);
7169
+ binDataEntries.push({ id: binId, format, filename: binFilename });
7170
+ }
7171
+ }
7172
+ if (binDataEntries.length > 0) {
7173
+ const binXml = binDataEntries.map((e) => ` <hh:binData id="${e.id}" type="LINK" format="${e.format}" compress="NO" access="PUBLIC"><hh:sourceFile href="${e.filename}"/></hh:binData>`).join("\n");
7174
+ headerXml = headerXml.replace("</hh:refList>", `${binXml}
7175
+ </hh:refList>`);
7176
+ }
7013
7177
  const sectionXml = generateSectionXml(
7014
7178
  parseMarkdownToBlocks(markdown),
7015
- styleMap || void 0
7179
+ styleMap || void 0,
7180
+ imageMap.size > 0 ? imageMap : void 0
7016
7181
  );
7017
7182
  const zip = new JSZip6();
7018
7183
  zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
@@ -7028,8 +7193,7 @@ async function markdownToHwpx(markdown, options) {
7028
7193
  if (opts.images && opts.images.length > 0) {
7029
7194
  for (const img of opts.images) {
7030
7195
  const nameWithoutExt = img.filename.replace(/\.[^.]+$/, "");
7031
- const binDataPath = `BinData/${nameWithoutExt}`;
7032
- zip.file(binDataPath, img.data);
7196
+ zip.file(`BinData/${nameWithoutExt}`, img.data);
7033
7197
  }
7034
7198
  }
7035
7199
  return await zip.generateAsync({ type: "arraybuffer" });