hwpx-js 0.1.1 → 0.1.2

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.cjs CHANGED
@@ -34,7 +34,8 @@ __export(index_exports, {
34
34
  createDefaultStyles: () => createDefaultStyles,
35
35
  read: () => read,
36
36
  utils: () => utils_exports,
37
- write: () => write
37
+ write: () => write,
38
+ writePdf: () => writePdf2
38
39
  });
39
40
  module.exports = __toCommonJS(index_exports);
40
41
 
@@ -813,14 +814,15 @@ var XmlParser = class {
813
814
  // src/codecs/hwpx/xml/parse-header.ts
814
815
  function parseHeaderXml(xml) {
815
816
  const root = parseXml(xml);
817
+ const refList = findChild(root, "hh:refList") || root;
816
818
  return {
817
- fontFaces: parseFontFaces(root),
818
- borderFills: parseBorderFills(root),
819
- charProperties: parseCharProperties(root),
820
- paraProperties: parseParaProperties(root),
821
- styles: parseStyles(root),
822
- bulletProperties: parseBullets(root),
823
- numberingProperties: parseNumberings(root),
819
+ fontFaces: parseFontFaces(refList),
820
+ borderFills: parseBorderFills(refList),
821
+ charProperties: parseCharProperties(refList),
822
+ paraProperties: parseParaProperties(refList),
823
+ styles: parseStyles(refList),
824
+ bulletProperties: parseBullets(refList),
825
+ numberingProperties: parseNumberings(refList),
824
826
  compatibleDoc: parseCompatibleDoc(root)
825
827
  };
826
828
  }
@@ -894,15 +896,21 @@ function parseCharProperties(root) {
894
896
  if (!propsNode) return props;
895
897
  for (const cpNode of findChildren(propsNode, "hh:charPr")) {
896
898
  const fontRefNode = findChild(cpNode, "hh:fontRef");
899
+ const hasBoldElement = !!findChild(cpNode, "hh:bold");
900
+ const hasItalicElement = !!findChild(cpNode, "hh:italic");
901
+ const underlineNode = findChild(cpNode, "hh:underline");
902
+ const strikeoutNode = findChild(cpNode, "hh:strikeout");
903
+ const underline = underlineNode ? attrStr(underlineNode, "type", "NONE") : attrStr(cpNode, "underline", "NONE");
904
+ const strikeout = strikeoutNode ? attrStr(strikeoutNode, "shape", "NONE") === "NONE" ? "NONE" : "CONTINUOUS" : attrStr(cpNode, "strikeout", "NONE");
897
905
  props.push({
898
906
  id: attrInt(cpNode, "id"),
899
907
  height: attrInt(cpNode, "height", 1e3),
900
908
  textColor: parseColor(attrStr(cpNode, "textColor", "#000000")),
901
- shadeColor: cpNode.attrs["shadeColor"] ? parseColor(attrStr(cpNode, "shadeColor")) : void 0,
902
- bold: attrBool(cpNode, "bold"),
903
- italic: attrBool(cpNode, "italic"),
904
- underline: attrStr(cpNode, "underline", "NONE"),
905
- strikeout: attrStr(cpNode, "strikeout", "NONE"),
909
+ shadeColor: cpNode.attrs["shadeColor"] && cpNode.attrs["shadeColor"] !== "none" ? parseColor(attrStr(cpNode, "shadeColor")) : void 0,
910
+ bold: hasBoldElement || attrBool(cpNode, "bold"),
911
+ italic: hasItalicElement || attrBool(cpNode, "italic"),
912
+ underline,
913
+ strikeout,
906
914
  useFontSpace: attrBool(cpNode, "useFontSpace"),
907
915
  useKerning: attrBool(cpNode, "useKerning"),
908
916
  spacing: cpNode.attrs["spacing"] !== void 0 ? attrInt(cpNode, "spacing") : void 0,
@@ -926,24 +934,54 @@ function parseParaProperties(root) {
926
934
  const propsNode = findChild(root, "hh:paraProperties");
927
935
  if (!propsNode) return props;
928
936
  for (const ppNode of findChildren(propsNode, "hh:paraPr")) {
929
- const marginNode = findChild(ppNode, "hh:parMargin");
930
- const lineSpacingNode = findChild(ppNode, "hh:lineSpacing");
937
+ const alignNode = findChild(ppNode, "hh:align");
938
+ const alignment = alignNode ? attrStr(alignNode, "horizontal", "JUSTIFY") : attrStr(ppNode, "align", "JUSTIFY");
939
+ let marginNode = findChild(ppNode, "hh:parMargin") || findChild(ppNode, "hh:margin");
940
+ let lineSpacingNode = findChild(ppNode, "hh:lineSpacing");
941
+ const switchNode = findChild(ppNode, "hp:switch");
942
+ if (switchNode) {
943
+ const caseNode = findChild(switchNode, "hp:case");
944
+ if (caseNode) {
945
+ if (!marginNode) marginNode = findChild(caseNode, "hh:margin");
946
+ if (!lineSpacingNode) lineSpacingNode = findChild(caseNode, "hh:lineSpacing");
947
+ }
948
+ }
949
+ let paraMargin = { left: 0, right: 0, indent: 0, prevSpacing: 0, nextSpacing: 0 };
950
+ if (marginNode) {
951
+ const leftChild = findChild(marginNode, "hc:left");
952
+ if (leftChild) {
953
+ const intentChild = findChild(marginNode, "hc:intent");
954
+ const rightChild = findChild(marginNode, "hc:right");
955
+ const prevChild = findChild(marginNode, "hc:prev");
956
+ const nextChild = findChild(marginNode, "hc:next");
957
+ paraMargin = {
958
+ left: leftChild ? attrInt(leftChild, "value") : 0,
959
+ right: rightChild ? attrInt(rightChild, "value") : 0,
960
+ indent: intentChild ? attrInt(intentChild, "value") : 0,
961
+ prevSpacing: prevChild ? attrInt(prevChild, "value") : 0,
962
+ nextSpacing: nextChild ? attrInt(nextChild, "value") : 0
963
+ };
964
+ } else {
965
+ paraMargin = {
966
+ left: attrInt(marginNode, "left"),
967
+ right: attrInt(marginNode, "right"),
968
+ indent: attrInt(marginNode, "indent"),
969
+ prevSpacing: attrInt(marginNode, "prev"),
970
+ nextSpacing: attrInt(marginNode, "next")
971
+ };
972
+ }
973
+ }
974
+ const headingNode = findChild(ppNode, "hh:heading");
931
975
  props.push({
932
976
  id: attrInt(ppNode, "id"),
933
- alignment: attrStr(ppNode, "align", "JUSTIFY"),
934
- heading: ppNode.attrs["heading"] ? ppNode.attrs["heading"] : void 0,
977
+ alignment,
978
+ heading: headingNode ? attrStr(headingNode, "type", "NONE") : ppNode.attrs["heading"] ? ppNode.attrs["heading"] : void 0,
935
979
  breakBefore: ppNode.attrs["breakBefore"] ? ppNode.attrs["breakBefore"] : void 0,
936
980
  lineSpacing: lineSpacingNode ? {
937
981
  type: attrStr(lineSpacingNode, "type", "PERCENT"),
938
982
  value: attrInt(lineSpacingNode, "value", 160)
939
983
  } : { type: "PERCENT", value: 160 },
940
- paraMargin: marginNode ? {
941
- left: attrInt(marginNode, "left"),
942
- right: attrInt(marginNode, "right"),
943
- indent: attrInt(marginNode, "indent"),
944
- prevSpacing: attrInt(marginNode, "prev"),
945
- nextSpacing: attrInt(marginNode, "next")
946
- } : { left: 0, right: 0, indent: 0, prevSpacing: 0, nextSpacing: 0 }
984
+ paraMargin
947
985
  });
948
986
  }
949
987
  return props;
@@ -1015,12 +1053,24 @@ function parseSectionXml(xml) {
1015
1053
  };
1016
1054
  }
1017
1055
  function parseSectionDef(root) {
1018
- const secPr = findChild(root, "hs:secPr");
1056
+ let secPr = findChild(root, "hs:secPr");
1057
+ if (!secPr) {
1058
+ for (const p of findChildren(root, "hp:p")) {
1059
+ for (const run of findChildren(p, "hp:run")) {
1060
+ const found = findChild(run, "hp:secPr");
1061
+ if (found) {
1062
+ secPr = found;
1063
+ break;
1064
+ }
1065
+ }
1066
+ if (secPr) break;
1067
+ }
1068
+ }
1019
1069
  if (!secPr) {
1020
1070
  return defaultSectionDef();
1021
1071
  }
1022
- const pagePr = findChild(secPr, "hs:pagePr");
1023
- const pageMarginNode = findChild(secPr, "hs:pageMargin");
1072
+ const pagePr = findChild(secPr, "hp:pagePr") || findChild(secPr, "hs:pagePr");
1073
+ const pageMarginNode = findChild(secPr, "hs:pageMargin") || (pagePr ? findChild(pagePr, "hp:margin") || findChild(pagePr, "hs:margin") : void 0);
1024
1074
  const colPr = findChild(secPr, "hs:colPr");
1025
1075
  let columns;
1026
1076
  if (colPr && attrInt(colPr, "count", 1) > 1) {
@@ -1046,7 +1096,7 @@ function parseSectionDef(root) {
1046
1096
  return {
1047
1097
  pageWidth: pagePr ? attrInt(pagePr, "width", 59528) : 59528,
1048
1098
  pageHeight: pagePr ? attrInt(pagePr, "height", 84188) : 84188,
1049
- landscape: pagePr ? attrStr(pagePr, "landscape") === "LANDSCAPE" : false,
1099
+ landscape: pagePr ? attrStr(pagePr, "landscape") === "LANDSCAPE" || attrStr(pagePr, "landscape") === "WIDELY" : false,
1050
1100
  gutterType: pagePr ? attrStr(pagePr, "gutterType", "LEFT_ONLY") : "LEFT_ONLY",
1051
1101
  pageMargin: pageMarginNode ? parsePageMargin(pageMarginNode) : defaultPageMargin(),
1052
1102
  columns,
@@ -1076,11 +1126,11 @@ function parseParagraph(pNode) {
1076
1126
  for (const runNode of findChildren(pNode, "hp:run")) {
1077
1127
  const charPrIDRef = attrInt(runNode, "charPrIDRef");
1078
1128
  const lineBreak = findChild(runNode, "hp:lineBreak");
1079
- const pageBreak = findChild(runNode, "hp:pageBreak");
1129
+ const pageBreak2 = findChild(runNode, "hp:pageBreak");
1080
1130
  const colBreak = findChild(runNode, "hp:colBreak");
1081
1131
  if (lineBreak) {
1082
1132
  runs.push({ t: "break", breakType: "LINE", charPrIDRef });
1083
- } else if (pageBreak) {
1133
+ } else if (pageBreak2) {
1084
1134
  runs.push({ t: "break", breakType: "PAGE", charPrIDRef });
1085
1135
  } else if (colBreak) {
1086
1136
  runs.push({ t: "break", breakType: "COLUMN", charPrIDRef });
@@ -1095,29 +1145,36 @@ function parseParagraph(pNode) {
1095
1145
  runs.push({ t: "picture", picture: parsePicture(picNode), charPrIDRef });
1096
1146
  continue;
1097
1147
  }
1098
- const runTextNode = findChild(runNode, "hp:runText");
1148
+ const runTextNode = findChild(runNode, "hp:runText") || findChild(runNode, "hp:t");
1099
1149
  const text = runTextNode ? getTextContent(runTextNode) : "";
1100
1150
  runs.push({ t: "text", text, charPrIDRef });
1101
1151
  }
1102
1152
  }
1153
+ const pageBreakVal = attrStr(pNode, "pageBreak", "0");
1154
+ const pageBreak = pageBreakVal === "1" || pageBreakVal === "true";
1103
1155
  return {
1104
1156
  paraPrIDRef: attrInt(pNode, "paraPrIDRef"),
1105
1157
  styleIDRef: attrInt(pNode, "styleIDRef"),
1106
- runs
1158
+ runs,
1159
+ ...pageBreak ? { pageBreak: true } : {}
1107
1160
  };
1108
1161
  }
1109
1162
  function parseTable(tblNode) {
1110
1163
  const rowCount = attrInt(tblNode, "rowCnt", 1);
1111
1164
  const colCount = attrInt(tblNode, "colCnt", 1);
1112
- const width = attrInt(tblNode, "width", 0);
1113
1165
  const borderFillIDRef = attrInt(tblNode, "borderFillIDRef", 1);
1114
1166
  const cellSpacing = attrInt(tblNode, "cellSpacing", 0);
1167
+ const szNode = findChild(tblNode, "hp:sz");
1168
+ const width = szNode ? attrInt(szNode, "width", 0) : attrInt(tblNode, "width", 0);
1115
1169
  const colSzNodes = findChildren(tblNode, "hp:colSz");
1116
- const colWidths = colSzNodes.map((n) => attrInt(n, "width", 0));
1170
+ let colWidths = colSzNodes.map((n) => attrInt(n, "width", 0));
1117
1171
  const rows = [];
1118
1172
  for (const trNode of findChildren(tblNode, "hp:tr")) {
1119
1173
  rows.push(parseTableRow(trNode));
1120
1174
  }
1175
+ if (colWidths.length === 0 && rows.length > 0) {
1176
+ colWidths = rows[0].cells.map((c) => c.width);
1177
+ }
1121
1178
  return {
1122
1179
  rowCount,
1123
1180
  colCount,
@@ -1129,21 +1186,31 @@ function parseTable(tblNode) {
1129
1186
  };
1130
1187
  }
1131
1188
  function parseTableRow(trNode) {
1132
- const height = attrInt(trNode, "height", 0);
1133
1189
  const cells = [];
1134
1190
  for (const tcNode of findChildren(trNode, "hp:tc")) {
1135
1191
  cells.push(parseTableCell(tcNode));
1136
1192
  }
1193
+ const height = attrInt(trNode, "height", 0) || (cells.length > 0 ? cells[0].height : 0);
1137
1194
  return { height, cells };
1138
1195
  }
1139
1196
  function parseTableCell(tcNode) {
1140
- const colSpan = attrInt(tcNode, "colSpan", 1);
1141
- const rowSpan = attrInt(tcNode, "rowSpan", 1);
1142
- const width = attrInt(tcNode, "width", 0);
1143
- const height = attrInt(tcNode, "height", 0);
1197
+ const cellSpanNode = findChild(tcNode, "hp:cellSpan");
1198
+ const colSpan = cellSpanNode ? attrInt(cellSpanNode, "colSpan", 1) : attrInt(tcNode, "colSpan", 1);
1199
+ const rowSpan = cellSpanNode ? attrInt(cellSpanNode, "rowSpan", 1) : attrInt(tcNode, "rowSpan", 1);
1200
+ const cellSzNode = findChild(tcNode, "hp:cellSz");
1201
+ const width = cellSzNode ? attrInt(cellSzNode, "width", 0) : attrInt(tcNode, "width", 0);
1202
+ const height = cellSzNode ? attrInt(cellSzNode, "height", 0) : attrInt(tcNode, "height", 0);
1144
1203
  const borderFillIDRef = attrInt(tcNode, "borderFillIDRef", 1);
1145
1204
  let padding;
1146
- if (tcNode.attrs["paddingLeft"] !== void 0) {
1205
+ const cellMarginNode = findChild(tcNode, "hp:cellMargin");
1206
+ if (cellMarginNode) {
1207
+ padding = {
1208
+ left: attrInt(cellMarginNode, "left"),
1209
+ right: attrInt(cellMarginNode, "right"),
1210
+ top: attrInt(cellMarginNode, "top"),
1211
+ bottom: attrInt(cellMarginNode, "bottom")
1212
+ };
1213
+ } else if (tcNode.attrs["paddingLeft"] !== void 0) {
1147
1214
  padding = {
1148
1215
  left: attrInt(tcNode, "paddingLeft"),
1149
1216
  right: attrInt(tcNode, "paddingRight"),
@@ -2060,6 +2127,303 @@ function detectFormat(data) {
2060
2127
  return "unknown";
2061
2128
  }
2062
2129
 
2130
+ // src/codecs/pdf/writer.ts
2131
+ var PdfBuilder = class {
2132
+ constructor() {
2133
+ this.objects = [];
2134
+ this.offsets = [];
2135
+ this.output = "";
2136
+ }
2137
+ nextId() {
2138
+ return this.objects.length + 1;
2139
+ }
2140
+ addObject(content) {
2141
+ const id = this.nextId();
2142
+ this.objects.push(content);
2143
+ return id;
2144
+ }
2145
+ build() {
2146
+ this.output = "%PDF-1.4\n%\xC0\xC1\xC2\xC3\n";
2147
+ for (let i = 0; i < this.objects.length; i++) {
2148
+ this.offsets.push(this.output.length);
2149
+ this.output += `${i + 1} 0 obj
2150
+ ${this.objects[i]}
2151
+ endobj
2152
+ `;
2153
+ }
2154
+ const xrefOffset = this.output.length;
2155
+ this.output += "xref\n";
2156
+ this.output += `0 ${this.objects.length + 1}
2157
+ `;
2158
+ this.output += "0000000000 65535 f \n";
2159
+ for (const off of this.offsets) {
2160
+ this.output += off.toString().padStart(10, "0") + " 00000 n \n";
2161
+ }
2162
+ this.output += "trailer\n";
2163
+ this.output += `<< /Size ${this.objects.length + 1} /Root 1 0 R >>
2164
+ `;
2165
+ this.output += "startxref\n";
2166
+ this.output += `${xrefOffset}
2167
+ `;
2168
+ this.output += "%%EOF\n";
2169
+ return stringToBytes(this.output);
2170
+ }
2171
+ };
2172
+ function writePdf(doc, opts) {
2173
+ const korFont = opts?.fontName || "Malgun Gothic";
2174
+ const latFont = opts?.latinFontName || "Helvetica";
2175
+ const pdf = new PdfBuilder();
2176
+ const catalogId = pdf.addObject("");
2177
+ const pagesId = pdf.addObject("");
2178
+ const cidFontId = pdf.addObject(
2179
+ `<< /Type /Font /Subtype /CIDFontType2 /BaseFont /${sanitizeName(korFont)} /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /DW 1000 >>`
2180
+ );
2181
+ const korFontId = pdf.addObject(
2182
+ `<< /Type /Font /Subtype /Type0 /BaseFont /${sanitizeName(korFont)} /Encoding /Identity-H /DescendantFonts [${cidFontId} 0 R] /ToUnicode ${pdf.nextId() + 1} 0 R >>`
2183
+ );
2184
+ const cmapStream = buildToUnicodeCMap();
2185
+ const cmapId = pdf.addObject(
2186
+ `<< /Length ${cmapStream.length} >>
2187
+ stream
2188
+ ${cmapStream}
2189
+ endstream`
2190
+ );
2191
+ pdf.objects[korFontId - 1] = `<< /Type /Font /Subtype /Type0 /BaseFont /${sanitizeName(korFont)} /Encoding /Identity-H /DescendantFonts [${cidFontId} 0 R] /ToUnicode ${cmapId} 0 R >>`;
2192
+ const latFontId = pdf.addObject(
2193
+ `<< /Type /Font /Subtype /Type1 /BaseFont /${sanitizeName(latFont)} /Encoding /WinAnsiEncoding >>`
2194
+ );
2195
+ const fontResources = `/F1 ${korFontId} 0 R /F2 ${latFontId} 0 R`;
2196
+ const pageIds = [];
2197
+ for (const section of doc.sections) {
2198
+ const pageW = section.def.pageWidth / 7200 * 72;
2199
+ const pageH = section.def.pageHeight / 7200 * 72;
2200
+ const ml = section.def.pageMargin.left / 7200 * 72;
2201
+ const mr = section.def.pageMargin.right / 7200 * 72;
2202
+ const mt = section.def.pageMargin.top / 7200 * 72;
2203
+ const mb = section.def.pageMargin.bottom / 7200 * 72;
2204
+ const bodyW = pageW - ml - mr;
2205
+ const bodyH = pageH - mt - mb;
2206
+ const ctx = {
2207
+ doc,
2208
+ pdf,
2209
+ pagesId,
2210
+ fontResources,
2211
+ pageW,
2212
+ pageH,
2213
+ ml,
2214
+ mr,
2215
+ mt,
2216
+ mb,
2217
+ bodyW,
2218
+ bodyH,
2219
+ pageIds
2220
+ };
2221
+ renderSection(ctx, section);
2222
+ }
2223
+ pdf.objects[0] = `<< /Type /Catalog /Pages ${pagesId} 0 R >>`;
2224
+ const kids = pageIds.map((id) => `${id} 0 R`).join(" ");
2225
+ pdf.objects[1] = `<< /Type /Pages /Kids [${kids}] /Count ${pageIds.length} >>`;
2226
+ return pdf.build();
2227
+ }
2228
+ function renderSection(ctx, section) {
2229
+ let page = newPage(ctx);
2230
+ for (const para of section.paragraphs) {
2231
+ for (const run of para.runs) {
2232
+ if (run.t === "text") {
2233
+ const fontSize = getFontSize(ctx.doc, run.charPrIDRef);
2234
+ const lineHeight = fontSize * 1.6;
2235
+ if (page.y - lineHeight < 0) {
2236
+ flushPage(ctx, page);
2237
+ page = newPage(ctx);
2238
+ }
2239
+ if (run.text) {
2240
+ const color = getTextColor(ctx.doc, run.charPrIDRef);
2241
+ const bold = isBold(ctx.doc, run.charPrIDRef);
2242
+ if (color !== "0 0 0") {
2243
+ page.ops.push(color + " rg");
2244
+ }
2245
+ const lines = wrapText(run.text, fontSize, ctx.bodyW);
2246
+ for (const line of lines) {
2247
+ if (page.y - lineHeight < 0) {
2248
+ flushPage(ctx, page);
2249
+ page = newPage(ctx);
2250
+ }
2251
+ page.ops.push("BT");
2252
+ page.ops.push(`/F1 ${fontSize} Tf`);
2253
+ page.ops.push(`${ctx.ml} ${ctx.mt + page.y - lineHeight} Td`);
2254
+ page.ops.push(`<${toUtf16Hex(line)}> Tj`);
2255
+ page.ops.push("ET");
2256
+ page.y -= lineHeight;
2257
+ }
2258
+ if (color !== "0 0 0") {
2259
+ page.ops.push("0 0 0 rg");
2260
+ }
2261
+ } else {
2262
+ page.y -= fontSize * 1.6;
2263
+ }
2264
+ } else if (run.t === "table") {
2265
+ const tableHeight = estimateTableHeight(run.table, ctx.doc);
2266
+ if (page.y - tableHeight < 0 && page.y < ctx.bodyH - 10) {
2267
+ flushPage(ctx, page);
2268
+ page = newPage(ctx);
2269
+ }
2270
+ renderTable(ctx, page, run.table);
2271
+ }
2272
+ }
2273
+ }
2274
+ flushPage(ctx, page);
2275
+ }
2276
+ function newPage(ctx) {
2277
+ return { ops: [], y: ctx.bodyH };
2278
+ }
2279
+ function flushPage(ctx, page) {
2280
+ if (page.ops.length === 0) return;
2281
+ const stream = page.ops.join("\n");
2282
+ const streamId = ctx.pdf.addObject(
2283
+ `<< /Length ${byteLength(stream)} >>
2284
+ stream
2285
+ ${stream}
2286
+ endstream`
2287
+ );
2288
+ const pageId = ctx.pdf.addObject(
2289
+ `<< /Type /Page /Parent ${ctx.pagesId} 0 R /MediaBox [0 0 ${fmt(ctx.pageW)} ${fmt(ctx.pageH)}] /Resources << /Font << ${ctx.fontResources} >> >> /Contents ${streamId} 0 R >>`
2290
+ );
2291
+ ctx.pageIds.push(pageId);
2292
+ }
2293
+ function renderTable(ctx, page, table) {
2294
+ const tableW = table.width / 7200 * 72;
2295
+ const scale = Math.min(1, ctx.bodyW / tableW);
2296
+ const startX = ctx.ml;
2297
+ const startY = ctx.mt + page.y;
2298
+ for (const row of table.rows) {
2299
+ const rowH = row.height / 7200 * 72 * scale;
2300
+ let cellX = startX;
2301
+ for (const cell of row.cells) {
2302
+ const cellW = cell.width / 7200 * 72 * scale;
2303
+ const cellH = cell.height / 7200 * 72 * scale;
2304
+ const cellY = startY - rowH;
2305
+ page.ops.push("0.5 w");
2306
+ page.ops.push(`${fmt(cellX)} ${fmt(cellY)} ${fmt(cellW)} ${fmt(cellH)} re S`);
2307
+ const text = cell.paragraphs.flatMap((p) => p.runs.filter((r) => r.t === "text").map((r) => r.text)).join(" ");
2308
+ if (text) {
2309
+ const fontSize = 8 * scale;
2310
+ const textX = cellX + 3;
2311
+ const textY = cellY + cellH - fontSize - 2;
2312
+ page.ops.push("BT");
2313
+ page.ops.push(`/F1 ${fmt(fontSize)} Tf`);
2314
+ page.ops.push(`${fmt(textX)} ${fmt(textY)} Td`);
2315
+ page.ops.push(`<${toUtf16Hex(text.substring(0, 100))}> Tj`);
2316
+ page.ops.push("ET");
2317
+ }
2318
+ cellX += cellW;
2319
+ }
2320
+ page.y -= rowH;
2321
+ startY === ctx.mt + page.y + rowH;
2322
+ }
2323
+ }
2324
+ function estimateTableHeight(table, doc) {
2325
+ let h = 0;
2326
+ for (const row of table.rows) {
2327
+ h += row.height / 7200 * 72;
2328
+ }
2329
+ return h;
2330
+ }
2331
+ function getFontSize(doc, charPrIDRef) {
2332
+ const cp = doc.head.charProperties.find((c) => c.id === charPrIDRef);
2333
+ if (!cp) return 10;
2334
+ return cp.height / 100;
2335
+ }
2336
+ function getTextColor(doc, charPrIDRef) {
2337
+ const cp = doc.head.charProperties.find((c) => c.id === charPrIDRef);
2338
+ if (!cp || cp.textColor === 0) return "0 0 0";
2339
+ const r = (cp.textColor & 255) / 255;
2340
+ const g = (cp.textColor >> 8 & 255) / 255;
2341
+ const b = (cp.textColor >> 16 & 255) / 255;
2342
+ return `${fmt(r)} ${fmt(g)} ${fmt(b)}`;
2343
+ }
2344
+ function isBold(doc, charPrIDRef) {
2345
+ const cp = doc.head.charProperties.find((c) => c.id === charPrIDRef);
2346
+ return cp?.bold || false;
2347
+ }
2348
+ function wrapText(text, fontSize, maxWidth) {
2349
+ const lines = [];
2350
+ let current = "";
2351
+ let currentWidth = 0;
2352
+ for (const ch of text) {
2353
+ const w = ch.charCodeAt(0) > 127 ? fontSize : fontSize * 0.5;
2354
+ if (currentWidth + w > maxWidth && current) {
2355
+ lines.push(current);
2356
+ current = "";
2357
+ currentWidth = 0;
2358
+ }
2359
+ current += ch;
2360
+ currentWidth += w;
2361
+ }
2362
+ if (current) lines.push(current);
2363
+ return lines.length > 0 ? lines : [""];
2364
+ }
2365
+ function buildToUnicodeCMap() {
2366
+ return [
2367
+ "/CIDInit /ProcSet findresource begin",
2368
+ "12 dict begin",
2369
+ "begincmap",
2370
+ "/CIDSystemInfo",
2371
+ "<< /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def",
2372
+ "/CMapName /Adobe-Identity-UCS def",
2373
+ "/CMapType 2 def",
2374
+ "1 begincodespacerange",
2375
+ "<0000> <FFFF>",
2376
+ "endcodespacerange",
2377
+ "1 beginbfrange",
2378
+ "<0000> <FFFF> <0000>",
2379
+ "endbfrange",
2380
+ "endcmap",
2381
+ "CMapName currentdict /CMap defineresource pop",
2382
+ "end",
2383
+ "end"
2384
+ ].join("\n");
2385
+ }
2386
+ function toUtf16Hex(str) {
2387
+ let hex = "";
2388
+ for (let i = 0; i < str.length; i++) {
2389
+ const code = str.charCodeAt(i);
2390
+ hex += code.toString(16).padStart(4, "0");
2391
+ }
2392
+ return hex.toUpperCase();
2393
+ }
2394
+ function sanitizeName(name) {
2395
+ return name.replace(/[^a-zA-Z0-9]/g, "");
2396
+ }
2397
+ function fmt(n) {
2398
+ return Number(n.toFixed(2)).toString();
2399
+ }
2400
+ function byteLength(str) {
2401
+ let len = 0;
2402
+ for (let i = 0; i < str.length; i++) {
2403
+ const code = str.charCodeAt(i);
2404
+ if (code <= 127) len++;
2405
+ else if (code <= 2047) len += 2;
2406
+ else len += 3;
2407
+ }
2408
+ return len;
2409
+ }
2410
+ function stringToBytes(str) {
2411
+ const bytes = [];
2412
+ for (let i = 0; i < str.length; i++) {
2413
+ const code = str.charCodeAt(i);
2414
+ if (code <= 255) {
2415
+ bytes.push(code);
2416
+ } else {
2417
+ if (code <= 2047) {
2418
+ bytes.push(192 | code >> 6, 128 | code & 63);
2419
+ } else {
2420
+ bytes.push(224 | code >> 12, 128 | code >> 6 & 63, 128 | code & 63);
2421
+ }
2422
+ }
2423
+ }
2424
+ return new Uint8Array(bytes);
2425
+ }
2426
+
2063
2427
  // src/utils/id.ts
2064
2428
  var IdCounter = class {
2065
2429
  constructor(start = 0) {
@@ -2392,6 +2756,9 @@ function read(data, opts) {
2392
2756
  }
2393
2757
  return readHwpx(data, opts);
2394
2758
  }
2759
+ function writePdf2(doc, opts) {
2760
+ return writePdf(doc, opts);
2761
+ }
2395
2762
  // Annotate the CommonJS export names for ESM import in node:
2396
2763
  0 && (module.exports = {
2397
2764
  HWPXBuilder,
@@ -2408,6 +2775,7 @@ function read(data, opts) {
2408
2775
  createDefaultStyles,
2409
2776
  read,
2410
2777
  utils,
2411
- write
2778
+ write,
2779
+ writePdf
2412
2780
  });
2413
2781
  //# sourceMappingURL=index.cjs.map