kordoc 3.16.2 → 3.18.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.
- package/README.md +37 -12
- package/dist/{-C4FVXHIP.js → -OUCPI6B3.js} +9 -7
- package/dist/{chunk-HECUYZZK.js → chunk-4YEZTZAR.js} +79 -3
- package/dist/chunk-4YEZTZAR.js.map +1 -0
- package/dist/{chunk-72LLOLFX.cjs → chunk-5HDBLRVP.cjs} +45 -9
- package/dist/chunk-5HDBLRVP.cjs.map +1 -0
- package/dist/{chunk-4WI7QXEG.js → chunk-6Y4KKPC3.js} +2 -2
- package/dist/chunk-DCZVOIEO.cjs.map +1 -1
- package/dist/{chunk-EJ2ZIYTO.js → chunk-GIXXV52X.js} +39 -3
- package/dist/chunk-GIXXV52X.js.map +1 -0
- package/dist/chunk-GS7T56RP.cjs.map +1 -1
- package/dist/{chunk-EUEKDZ7O.js → chunk-PWHM3KAA.js} +535 -83
- package/dist/chunk-PWHM3KAA.js.map +1 -0
- package/dist/{chunk-WR5LHRXO.js → chunk-VP34RO24.js} +3 -3
- package/dist/{chunk-IS3IK7UT.js → chunk-YWIYGXLI.js} +39 -3
- package/dist/chunk-YWIYGXLI.js.map +1 -0
- package/dist/{chunk-E4Y73XRH.js → chunk-ZTUQYITH.js} +127 -68
- package/dist/chunk-ZTUQYITH.js.map +1 -0
- package/dist/cli.js +18 -15
- package/dist/cli.js.map +1 -1
- package/dist/formula-5NKVS2LR.cjs.map +1 -1
- package/dist/index.cjs +1045 -459
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -3
- package/dist/index.d.ts +121 -3
- package/dist/index.js +784 -198
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +22 -10
- package/dist/mcp.js.map +1 -1
- package/dist/page-range-P7SDW6LR.cjs.map +1 -1
- package/dist/{parser-GWL72XYS.js → parser-5D6BQYTX.js} +2 -2
- package/dist/{parser-CMPNM6ZL.js → parser-NZAE7PBE.js} +3 -3
- package/dist/{parser-YVRTKGKO.cjs → parser-S34YR2SH.cjs} +14 -14
- package/dist/parser-S34YR2SH.cjs.map +1 -0
- package/dist/provider-G4C2V2PD.cjs.map +1 -1
- package/dist/render-HRAW7ASR.js +10 -0
- package/dist/seal-CK64CXWO.js +10 -0
- package/dist/{watch-WLI6K3IR.js → watch-2EFXBRYK.js} +7 -7
- package/package.json +1 -1
- package/dist/chunk-72LLOLFX.cjs.map +0 -1
- package/dist/chunk-E4Y73XRH.js.map +0 -1
- package/dist/chunk-EJ2ZIYTO.js.map +0 -1
- package/dist/chunk-EUEKDZ7O.js.map +0 -1
- package/dist/chunk-HECUYZZK.js.map +0 -1
- package/dist/chunk-IS3IK7UT.js.map +0 -1
- package/dist/parser-YVRTKGKO.cjs.map +0 -1
- package/dist/render-A2LFMJCP.js +0 -10
- package/dist/seal-KA4VAV2Z.js +0 -10
- /package/dist/{-C4FVXHIP.js.map → -OUCPI6B3.js.map} +0 -0
- /package/dist/{chunk-4WI7QXEG.js.map → chunk-6Y4KKPC3.js.map} +0 -0
- /package/dist/{chunk-WR5LHRXO.js.map → chunk-VP34RO24.js.map} +0 -0
- /package/dist/{parser-GWL72XYS.js.map → parser-5D6BQYTX.js.map} +0 -0
- /package/dist/{parser-CMPNM6ZL.js.map → parser-NZAE7PBE.js.map} +0 -0
- /package/dist/{render-A2LFMJCP.js.map → render-HRAW7ASR.js.map} +0 -0
- /package/dist/{seal-KA4VAV2Z.js.map → seal-CK64CXWO.js.map} +0 -0
- /package/dist/{watch-WLI6K3IR.js.map → watch-2EFXBRYK.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
classifyError,
|
|
12
12
|
compareSectionPaths,
|
|
13
13
|
convertTableToText,
|
|
14
|
+
dedupeRunningHeaders,
|
|
14
15
|
flattenLayoutTables,
|
|
15
16
|
isPathTraversal,
|
|
16
17
|
mapPuaText,
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
sanitizeHref,
|
|
20
21
|
stripDtd,
|
|
21
22
|
toArrayBuffer
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-GIXXV52X.js";
|
|
23
24
|
import {
|
|
24
25
|
parsePageRange
|
|
25
26
|
} from "./chunk-GE43BE46.js";
|
|
@@ -2527,11 +2528,11 @@ function formatRoman(n, upper) {
|
|
|
2527
2528
|
const values = [1e3, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
|
|
2528
2529
|
const symbols = upper ? ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"] : ["m", "cm", "d", "cd", "c", "xc", "l", "xl", "x", "ix", "v", "iv", "i"];
|
|
2529
2530
|
let result = "";
|
|
2530
|
-
let
|
|
2531
|
+
let num4 = n;
|
|
2531
2532
|
for (let i = 0; i < values.length; i++) {
|
|
2532
|
-
while (
|
|
2533
|
+
while (num4 >= values[i]) {
|
|
2533
2534
|
result += symbols[i];
|
|
2534
|
-
|
|
2535
|
+
num4 -= values[i];
|
|
2535
2536
|
}
|
|
2536
2537
|
}
|
|
2537
2538
|
return result;
|
|
@@ -2539,11 +2540,11 @@ function formatRoman(n, upper) {
|
|
|
2539
2540
|
function formatLatin(n, upper) {
|
|
2540
2541
|
if (n <= 0) return "";
|
|
2541
2542
|
let result = "";
|
|
2542
|
-
let
|
|
2543
|
-
while (
|
|
2544
|
-
|
|
2545
|
-
result = String.fromCharCode((upper ? 65 : 97) +
|
|
2546
|
-
|
|
2543
|
+
let num4 = n;
|
|
2544
|
+
while (num4 > 0) {
|
|
2545
|
+
num4--;
|
|
2546
|
+
result = String.fromCharCode((upper ? 65 : 97) + num4 % 26) + result;
|
|
2547
|
+
num4 = Math.floor(num4 / 26);
|
|
2547
2548
|
}
|
|
2548
2549
|
return result;
|
|
2549
2550
|
}
|
|
@@ -2551,15 +2552,15 @@ function formatEastAsianNumber(n, digits, units, zero) {
|
|
|
2551
2552
|
if (n === 0) return zero;
|
|
2552
2553
|
if (n < 0 || n > 99999) return String(n);
|
|
2553
2554
|
let result = "";
|
|
2554
|
-
let
|
|
2555
|
+
let num4 = n;
|
|
2555
2556
|
let unit = 0;
|
|
2556
|
-
while (
|
|
2557
|
-
const d =
|
|
2557
|
+
while (num4 > 0) {
|
|
2558
|
+
const d = num4 % 10;
|
|
2558
2559
|
if (d > 0) {
|
|
2559
2560
|
const digitStr = d === 1 && unit > 0 ? "" : digits[d];
|
|
2560
2561
|
result = digitStr + units[unit] + result;
|
|
2561
2562
|
}
|
|
2562
|
-
|
|
2563
|
+
num4 = Math.floor(num4 / 10);
|
|
2563
2564
|
unit++;
|
|
2564
2565
|
}
|
|
2565
2566
|
return result;
|
|
@@ -2606,8 +2607,8 @@ function expandNumberingFormat(formatStr, counters, numbering) {
|
|
|
2606
2607
|
const idx = levelRef - 1;
|
|
2607
2608
|
const counterVal = counters[idx] ?? 0;
|
|
2608
2609
|
const start = numbering.startNumbers[idx] ?? 1;
|
|
2609
|
-
const
|
|
2610
|
-
result += formatNumber(
|
|
2610
|
+
const num4 = counterVal > 0 ? start - 1 + counterVal : start;
|
|
2611
|
+
result += formatNumber(num4, headFormatToNumFmt(numbering.numberFormats[idx] ?? 0));
|
|
2611
2612
|
i += 2;
|
|
2612
2613
|
continue;
|
|
2613
2614
|
}
|
|
@@ -2756,6 +2757,141 @@ function extractHwp5ImagesLenient(lcfb, blocks, warnings) {
|
|
|
2756
2757
|
return resolveImageBlocks(binDataMap, blocks, warnings);
|
|
2757
2758
|
}
|
|
2758
2759
|
|
|
2760
|
+
// src/image/transcode.ts
|
|
2761
|
+
import { deflateSync } from "zlib";
|
|
2762
|
+
var CRC_TABLE = (() => {
|
|
2763
|
+
const table = new Uint32Array(256);
|
|
2764
|
+
for (let n = 0; n < 256; n++) {
|
|
2765
|
+
let c = n;
|
|
2766
|
+
for (let k = 0; k < 8; k++) {
|
|
2767
|
+
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
2768
|
+
}
|
|
2769
|
+
table[n] = c >>> 0;
|
|
2770
|
+
}
|
|
2771
|
+
return table;
|
|
2772
|
+
})();
|
|
2773
|
+
function crc32(bytes) {
|
|
2774
|
+
let c = 4294967295;
|
|
2775
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
2776
|
+
c = CRC_TABLE[(c ^ bytes[i]) & 255] ^ c >>> 8;
|
|
2777
|
+
}
|
|
2778
|
+
return (c ^ 4294967295) >>> 0;
|
|
2779
|
+
}
|
|
2780
|
+
var BI_RGB = 0;
|
|
2781
|
+
var MAX_DIM = 32767;
|
|
2782
|
+
var MAX_PIXELS = 64e6;
|
|
2783
|
+
function bmpToPng(bmp) {
|
|
2784
|
+
if (bmp.length < 54) return null;
|
|
2785
|
+
if (bmp[0] !== 66 || bmp[1] !== 77) return null;
|
|
2786
|
+
const dv = new DataView(bmp.buffer, bmp.byteOffset, bmp.byteLength);
|
|
2787
|
+
const dataOffset = dv.getUint32(10, true);
|
|
2788
|
+
const headerSize = dv.getUint32(14, true);
|
|
2789
|
+
if (headerSize < 40) return null;
|
|
2790
|
+
const width = dv.getInt32(18, true);
|
|
2791
|
+
const rawHeight = dv.getInt32(22, true);
|
|
2792
|
+
const bitCount = dv.getUint16(28, true);
|
|
2793
|
+
const compression = dv.getUint32(30, true);
|
|
2794
|
+
if (compression !== BI_RGB) return null;
|
|
2795
|
+
if (bitCount !== 24 && bitCount !== 32) return null;
|
|
2796
|
+
if (width <= 0 || rawHeight === 0) return null;
|
|
2797
|
+
if (width > MAX_DIM || Math.abs(rawHeight) > MAX_DIM) return null;
|
|
2798
|
+
const topDown = rawHeight < 0;
|
|
2799
|
+
const height = Math.abs(rawHeight);
|
|
2800
|
+
if (width * height > MAX_PIXELS) return null;
|
|
2801
|
+
const bytesPerPixel = bitCount >> 3;
|
|
2802
|
+
const rowStride = width * bytesPerPixel + 3 & ~3;
|
|
2803
|
+
if (dataOffset + rowStride * height > bmp.length) return null;
|
|
2804
|
+
const rgba = new Uint8Array(width * height * 4);
|
|
2805
|
+
let anyAlpha = 0;
|
|
2806
|
+
for (let y = 0; y < height; y++) {
|
|
2807
|
+
const srcRow = topDown ? y : height - 1 - y;
|
|
2808
|
+
let src = dataOffset + srcRow * rowStride;
|
|
2809
|
+
let dst = y * width * 4;
|
|
2810
|
+
for (let x = 0; x < width; x++) {
|
|
2811
|
+
rgba[dst] = bmp[src + 2];
|
|
2812
|
+
rgba[dst + 1] = bmp[src + 1];
|
|
2813
|
+
rgba[dst + 2] = bmp[src];
|
|
2814
|
+
const a = bitCount === 32 ? bmp[src + 3] : 255;
|
|
2815
|
+
rgba[dst + 3] = a;
|
|
2816
|
+
anyAlpha |= a;
|
|
2817
|
+
src += bytesPerPixel;
|
|
2818
|
+
dst += 4;
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
if (bitCount === 32 && anyAlpha === 0) {
|
|
2822
|
+
for (let i = 3; i < rgba.length; i += 4) rgba[i] = 255;
|
|
2823
|
+
}
|
|
2824
|
+
return encodePng(width, height, rgba);
|
|
2825
|
+
}
|
|
2826
|
+
var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71, 13, 10, 26, 10);
|
|
2827
|
+
function chunk(type, data) {
|
|
2828
|
+
const body = new Uint8Array(4 + data.length);
|
|
2829
|
+
body[0] = type.charCodeAt(0);
|
|
2830
|
+
body[1] = type.charCodeAt(1);
|
|
2831
|
+
body[2] = type.charCodeAt(2);
|
|
2832
|
+
body[3] = type.charCodeAt(3);
|
|
2833
|
+
body.set(data, 4);
|
|
2834
|
+
const out = new Uint8Array(8 + data.length + 4);
|
|
2835
|
+
const dv = new DataView(out.buffer);
|
|
2836
|
+
dv.setUint32(0, data.length, false);
|
|
2837
|
+
out.set(body, 4);
|
|
2838
|
+
dv.setUint32(8 + data.length, crc32(body), false);
|
|
2839
|
+
return out;
|
|
2840
|
+
}
|
|
2841
|
+
function encodePng(width, height, rgba) {
|
|
2842
|
+
const ihdr = new Uint8Array(13);
|
|
2843
|
+
const iv = new DataView(ihdr.buffer);
|
|
2844
|
+
iv.setUint32(0, width, false);
|
|
2845
|
+
iv.setUint32(4, height, false);
|
|
2846
|
+
ihdr[8] = 8;
|
|
2847
|
+
ihdr[9] = 6;
|
|
2848
|
+
const stride = width * 4;
|
|
2849
|
+
const raw = new Uint8Array((stride + 1) * height);
|
|
2850
|
+
for (let y = 0; y < height; y++) {
|
|
2851
|
+
const rowStart = y * (stride + 1);
|
|
2852
|
+
raw[rowStart] = 0;
|
|
2853
|
+
raw.set(rgba.subarray(y * stride, y * stride + stride), rowStart + 1);
|
|
2854
|
+
}
|
|
2855
|
+
const idat = deflateSync(raw);
|
|
2856
|
+
const ihdrChunk = chunk("IHDR", ihdr);
|
|
2857
|
+
const idatChunk = chunk("IDAT", idat);
|
|
2858
|
+
const iendChunk = chunk("IEND", new Uint8Array(0));
|
|
2859
|
+
const out = new Uint8Array(PNG_SIGNATURE.length + ihdrChunk.length + idatChunk.length + iendChunk.length);
|
|
2860
|
+
let o = 0;
|
|
2861
|
+
out.set(PNG_SIGNATURE, o);
|
|
2862
|
+
o += PNG_SIGNATURE.length;
|
|
2863
|
+
out.set(ihdrChunk, o);
|
|
2864
|
+
o += ihdrChunk.length;
|
|
2865
|
+
out.set(idatChunk, o);
|
|
2866
|
+
o += idatChunk.length;
|
|
2867
|
+
out.set(iendChunk, o);
|
|
2868
|
+
return out;
|
|
2869
|
+
}
|
|
2870
|
+
var MAX_INLINE_MD_BYTES = 4 * 1024 * 1024;
|
|
2871
|
+
function escapeRegExp(s) {
|
|
2872
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2873
|
+
}
|
|
2874
|
+
function inlineImagesIntoMarkdown(markdown, images, opts) {
|
|
2875
|
+
const compress = opts?.compress !== false;
|
|
2876
|
+
let out = markdown;
|
|
2877
|
+
for (const img of images) {
|
|
2878
|
+
let bytes = img.data;
|
|
2879
|
+
let mime = img.mimeType;
|
|
2880
|
+
if (compress && mime === "image/bmp") {
|
|
2881
|
+
const png = bmpToPng(img.data);
|
|
2882
|
+
if (png) {
|
|
2883
|
+
bytes = png;
|
|
2884
|
+
mime = "image/png";
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
const base64 = Buffer.from(bytes).toString("base64");
|
|
2888
|
+
const dataUri = `data:${mime};base64,${base64}`;
|
|
2889
|
+
const re = new RegExp(`!\\[image\\]\\((?:images/)?${escapeRegExp(img.filename)}\\)`, "g");
|
|
2890
|
+
out = out.replace(re, () => ``);
|
|
2891
|
+
}
|
|
2892
|
+
return out;
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2759
2895
|
// src/hwp5/aes.ts
|
|
2760
2896
|
var S_BOX = new Uint8Array([
|
|
2761
2897
|
99,
|
|
@@ -3804,12 +3940,25 @@ function parseHwp5Document(buffer, options) {
|
|
|
3804
3940
|
}
|
|
3805
3941
|
const blocks = [...doc.headerBlocks, ...bodyBlocks, ...doc.footerBlocks];
|
|
3806
3942
|
const images = cfb ? extractHwp5Images(cfb.FileIndex, blocks, warnings) : extractHwp5ImagesLenient(lenientCfb, blocks, warnings);
|
|
3807
|
-
|
|
3943
|
+
let flatBlocks = flattenLayoutTables(blocks);
|
|
3944
|
+
if (options?.dedupeRunningHeaders) {
|
|
3945
|
+
const deduped = dedupeRunningHeaders(flatBlocks);
|
|
3946
|
+
const removed = flatBlocks.length - deduped.length;
|
|
3947
|
+
if (removed > 0) warnings.push({ message: `\uBC18\uBCF5 \uB7EC\uB2DD \uD5E4\uB354 ${removed}\uAC1C \uC81C\uAC70`, code: "HIDDEN_TEXT_FILTERED" });
|
|
3948
|
+
flatBlocks = deduped;
|
|
3949
|
+
}
|
|
3808
3950
|
if (docInfo) {
|
|
3809
3951
|
detectHwp5Headings(flatBlocks, docInfo);
|
|
3810
3952
|
}
|
|
3811
3953
|
const outline = flatBlocks.filter((b) => b.type === "heading" && b.level && b.text).map((b) => ({ level: b.level, text: b.text, pageNumber: b.pageNumber }));
|
|
3812
|
-
|
|
3954
|
+
let markdown = blocksToMarkdown(flatBlocks);
|
|
3955
|
+
if (options?.inlineImages && images.length > 0) {
|
|
3956
|
+
try {
|
|
3957
|
+
markdown = inlineImagesIntoMarkdown(markdown, images, { compress: true });
|
|
3958
|
+
} catch (inlineErr) {
|
|
3959
|
+
warnings.push({ message: `\uC774\uBBF8\uC9C0 \uC778\uB77C\uC778 \uC2E4\uD328 \u2014 \uC6D0\uBCF8 \uD30C\uC77C \uCC38\uC870\uB85C \uD3F4\uBC31: ${inlineErr instanceof Error ? inlineErr.message : "\uC54C \uC218 \uC5C6\uB294 \uC624\uB958"}`, code: "SKIPPED_IMAGE" });
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3813
3962
|
return { markdown, blocks: flatBlocks, metadata, outline: outline.length > 0 ? outline : void 0, warnings: warnings.length > 0 ? warnings : void 0, images: images.length > 0 ? images : void 0 };
|
|
3814
3963
|
}
|
|
3815
3964
|
function parseDocInfoStream(cfb, compressed) {
|
|
@@ -4175,11 +4324,11 @@ function applyCtrlEffect(ctrl, records, ctx) {
|
|
|
4175
4324
|
const attr = ctrl.data.readUInt32LE(4);
|
|
4176
4325
|
const type = attr & 15;
|
|
4177
4326
|
const format = attr >>> 4 & 255;
|
|
4178
|
-
const
|
|
4179
|
-
ctx.doc.autoCounters.set(type,
|
|
4327
|
+
const num4 = ctx.doc.autoCounters.get(type) ?? 1;
|
|
4328
|
+
ctx.doc.autoCounters.set(type, num4 + 1);
|
|
4180
4329
|
const prefix = ctrl.data.length >= 14 ? wcharAt(ctrl.data, 12) : "";
|
|
4181
4330
|
const suffix = ctrl.data.length >= 16 ? wcharAt(ctrl.data, 14) : "";
|
|
4182
|
-
ctrl.inlineText = `${prefix}${formatNumber(
|
|
4331
|
+
ctrl.inlineText = `${prefix}${formatNumber(num4, shapeFormatToNumFmt(format))}${suffix}`;
|
|
4183
4332
|
}
|
|
4184
4333
|
return;
|
|
4185
4334
|
}
|
|
@@ -4187,8 +4336,8 @@ function applyCtrlEffect(ctrl, records, ctx) {
|
|
|
4187
4336
|
if (ctrl.data.length >= 10) {
|
|
4188
4337
|
const attr = ctrl.data.readUInt32LE(4);
|
|
4189
4338
|
const type = attr & 15;
|
|
4190
|
-
const
|
|
4191
|
-
if (
|
|
4339
|
+
const num4 = ctrl.data.readUInt16LE(8);
|
|
4340
|
+
if (num4 > 0) ctx.doc.autoCounters.set(type, num4);
|
|
4192
4341
|
}
|
|
4193
4342
|
return;
|
|
4194
4343
|
}
|
|
@@ -4250,7 +4399,7 @@ function blocksPlainText(blocks, sep) {
|
|
|
4250
4399
|
return parts.join(sep).trim();
|
|
4251
4400
|
}
|
|
4252
4401
|
function applyNoteEffect(ctrl, records, ctx, autoType) {
|
|
4253
|
-
const
|
|
4402
|
+
const num4 = ctx.doc.autoCounters.get(autoType) ?? 1;
|
|
4254
4403
|
let before = "";
|
|
4255
4404
|
let after = "";
|
|
4256
4405
|
let shape = 0;
|
|
@@ -4261,11 +4410,11 @@ function applyNoteEffect(ctrl, records, ctx, autoType) {
|
|
|
4261
4410
|
if (ctrl.data.length >= 16) {
|
|
4262
4411
|
shape = ctrl.data.readUInt32LE(12) & 255;
|
|
4263
4412
|
}
|
|
4264
|
-
const formatted = formatNumber(
|
|
4413
|
+
const formatted = formatNumber(num4, shapeFormatToNumFmt(shape));
|
|
4265
4414
|
const marker = before || after ? `${before}${formatted}${after}` : `${formatted})`;
|
|
4266
4415
|
const content = blocksPlainText(parseListHeaderParagraphs(ctrl, records, ctx), " ");
|
|
4267
|
-
if ((ctx.doc.autoCounters.get(autoType) ?? 1) <=
|
|
4268
|
-
ctx.doc.autoCounters.set(autoType,
|
|
4416
|
+
if ((ctx.doc.autoCounters.get(autoType) ?? 1) <= num4) {
|
|
4417
|
+
ctx.doc.autoCounters.set(autoType, num4 + 1);
|
|
4269
4418
|
}
|
|
4270
4419
|
ctrl.inlineText = marker;
|
|
4271
4420
|
if (content) ctrl.footnote = content.startsWith(marker) ? content : `${marker} ${content}`;
|
|
@@ -16803,9 +16952,9 @@ var MAX_ROWS2 = 1e4;
|
|
|
16803
16952
|
var MAX_COLS2 = 200;
|
|
16804
16953
|
function cleanNumericValue(raw) {
|
|
16805
16954
|
if (!/^-?\d+\.\d+$/.test(raw)) return raw;
|
|
16806
|
-
const
|
|
16807
|
-
if (!isFinite(
|
|
16808
|
-
const cleaned = parseFloat(
|
|
16955
|
+
const num4 = parseFloat(raw);
|
|
16956
|
+
if (!isFinite(num4)) return raw;
|
|
16957
|
+
const cleaned = parseFloat(num4.toPrecision(15)).toString();
|
|
16809
16958
|
return cleaned;
|
|
16810
16959
|
}
|
|
16811
16960
|
function parseCellRef(ref) {
|
|
@@ -17148,17 +17297,17 @@ function decodeRk(rk) {
|
|
|
17148
17297
|
const fDiv100 = (rk & 1) !== 0;
|
|
17149
17298
|
const fInt = (rk & 2) !== 0;
|
|
17150
17299
|
const val30 = rk >> 2;
|
|
17151
|
-
let
|
|
17300
|
+
let num4;
|
|
17152
17301
|
if (fInt) {
|
|
17153
|
-
|
|
17302
|
+
num4 = val30;
|
|
17154
17303
|
} else {
|
|
17155
17304
|
const high32 = (rk & 4294967292) >>> 0;
|
|
17156
17305
|
const buf = Buffer.alloc(8);
|
|
17157
17306
|
buf.writeUInt32LE(0, 0);
|
|
17158
17307
|
buf.writeUInt32LE(high32, 4);
|
|
17159
|
-
|
|
17308
|
+
num4 = buf.readDoubleLE(0);
|
|
17160
17309
|
}
|
|
17161
|
-
return fDiv100 ?
|
|
17310
|
+
return fDiv100 ? num4 / 100 : num4;
|
|
17162
17311
|
}
|
|
17163
17312
|
function decodeMulRk(data) {
|
|
17164
17313
|
if (data.length < 6) return null;
|
|
@@ -17858,9 +18007,9 @@ function nodeToLatex(el) {
|
|
|
17858
18007
|
case "f": {
|
|
17859
18008
|
const n = firstKid(el, "num");
|
|
17860
18009
|
const d = firstKid(el, "den");
|
|
17861
|
-
const
|
|
18010
|
+
const num4 = n ? childrenToLatex(n) : "";
|
|
17862
18011
|
const den = d ? childrenToLatex(d) : "";
|
|
17863
|
-
return "\\frac" + grp(
|
|
18012
|
+
return "\\frac" + grp(num4) + grp(den);
|
|
17864
18013
|
}
|
|
17865
18014
|
// 첨자
|
|
17866
18015
|
case "sSup": {
|
|
@@ -20155,7 +20304,7 @@ function parseCentralDirectory(buf) {
|
|
|
20155
20304
|
}
|
|
20156
20305
|
return { entries, cdOffset, cdSize, eocdOffset };
|
|
20157
20306
|
}
|
|
20158
|
-
var
|
|
20307
|
+
var CRC_TABLE2 = (() => {
|
|
20159
20308
|
const table = new Uint32Array(256);
|
|
20160
20309
|
for (let n = 0; n < 256; n++) {
|
|
20161
20310
|
let c = n;
|
|
@@ -20164,10 +20313,10 @@ var CRC_TABLE = (() => {
|
|
|
20164
20313
|
}
|
|
20165
20314
|
return table;
|
|
20166
20315
|
})();
|
|
20167
|
-
function
|
|
20316
|
+
function crc322(data) {
|
|
20168
20317
|
let crc = 4294967295;
|
|
20169
20318
|
for (let i = 0; i < data.length; i++) {
|
|
20170
|
-
crc =
|
|
20319
|
+
crc = CRC_TABLE2[(crc ^ data[i]) & 255] ^ crc >>> 8;
|
|
20171
20320
|
}
|
|
20172
20321
|
return (crc ^ 4294967295) >>> 0;
|
|
20173
20322
|
}
|
|
@@ -20206,7 +20355,7 @@ function patchZipEntries(original, replacements, additions) {
|
|
|
20206
20355
|
const hview = new DataView(header.buffer, header.byteOffset, header.byteLength);
|
|
20207
20356
|
const method = e.method;
|
|
20208
20357
|
const compData = method === 0 ? newData : new Uint8Array(deflateRawSync(newData));
|
|
20209
|
-
const crc =
|
|
20358
|
+
const crc = crc322(newData);
|
|
20210
20359
|
const flags = e.flags & ~8;
|
|
20211
20360
|
hview.setUint16(6, flags, true);
|
|
20212
20361
|
hview.setUint32(14, crc, true);
|
|
@@ -20224,7 +20373,7 @@ function patchZipEntries(original, replacements, additions) {
|
|
|
20224
20373
|
const deflated = new Uint8Array(deflateRawSync(data));
|
|
20225
20374
|
const method = deflated.length < data.length ? 8 : 0;
|
|
20226
20375
|
const compData = method === 8 ? deflated : data;
|
|
20227
|
-
const crc =
|
|
20376
|
+
const crc = crc322(data);
|
|
20228
20377
|
const header = new Uint8Array(30 + nameBytes.length);
|
|
20229
20378
|
const hv = new DataView(header.buffer);
|
|
20230
20379
|
hv.setUint32(0, LOCAL_SIG, true);
|
|
@@ -21253,7 +21402,7 @@ function generateManifest(chartParts = []) {
|
|
|
21253
21402
|
</opf:spine>
|
|
21254
21403
|
</opf:package>`;
|
|
21255
21404
|
}
|
|
21256
|
-
function buildCharProperties(theme, gongmun, ratioVariants = []) {
|
|
21405
|
+
function buildCharProperties(theme, gongmun, ratioVariants = [], extraCharPrXmls = []) {
|
|
21257
21406
|
let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
|
|
21258
21407
|
if (gongmun) {
|
|
21259
21408
|
body = gongmun.bodyHeight;
|
|
@@ -21285,6 +21434,7 @@ function buildCharProperties(theme, gongmun, ratioVariants = []) {
|
|
|
21285
21434
|
charPr(rows.length + 3, body, true, true, 0, theme.body, r)
|
|
21286
21435
|
);
|
|
21287
21436
|
}
|
|
21437
|
+
rows.push(...extraCharPrXmls);
|
|
21288
21438
|
return `<hh:charProperties itemCnt="${rows.length}">
|
|
21289
21439
|
${rows.join("\n")}
|
|
21290
21440
|
</hh:charProperties>`;
|
|
@@ -21338,9 +21488,9 @@ ${heads}
|
|
|
21338
21488
|
</hh:numbering>
|
|
21339
21489
|
</hh:numberings>`;
|
|
21340
21490
|
}
|
|
21341
|
-
function generateHeaderXml(theme, gongmun, ratioVariants = []) {
|
|
21491
|
+
function generateHeaderXml(theme, gongmun, ratioVariants = [], remap = null) {
|
|
21342
21492
|
const bodyFace = gongmun?.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5";
|
|
21343
|
-
const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants);
|
|
21493
|
+
const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants, remap?.charPrXmls ?? []);
|
|
21344
21494
|
const paraPropsXml = buildParaProperties(gongmun);
|
|
21345
21495
|
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
21346
21496
|
<hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
|
|
@@ -21395,7 +21545,7 @@ function generateHeaderXml(theme, gongmun, ratioVariants = []) {
|
|
|
21395
21545
|
</hh:font>
|
|
21396
21546
|
</hh:fontface>
|
|
21397
21547
|
</hh:fontfaces>
|
|
21398
|
-
<hh:borderFills itemCnt="2">
|
|
21548
|
+
<hh:borderFills itemCnt="${2 + (remap?.borderFillXmls.length ?? 0)}">
|
|
21399
21549
|
<hh:borderFill id="1" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
21400
21550
|
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
21401
21551
|
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
@@ -21411,7 +21561,7 @@ function generateHeaderXml(theme, gongmun, ratioVariants = []) {
|
|
|
21411
21561
|
<hh:rightBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
21412
21562
|
<hh:topBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
21413
21563
|
<hh:bottomBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
21414
|
-
</hh:borderFill
|
|
21564
|
+
</hh:borderFill>${remap && remap.borderFillXmls.length ? "\n" + remap.borderFillXmls.join("\n") : ""}
|
|
21415
21565
|
</hh:borderFills>
|
|
21416
21566
|
${charPropsXml}
|
|
21417
21567
|
<hh:tabProperties itemCnt="0"/>
|
|
@@ -22143,23 +22293,47 @@ var tableIdCounter = TABLE_ID_BASE;
|
|
|
22143
22293
|
function nextTableId() {
|
|
22144
22294
|
return ++tableIdCounter;
|
|
22145
22295
|
}
|
|
22146
|
-
|
|
22296
|
+
var warnedTables = /* @__PURE__ */ new Set();
|
|
22297
|
+
function warnProfileMismatch(tblId, tp, rowCnt, colCnt) {
|
|
22298
|
+
if (warnedTables.has(tblId)) return;
|
|
22299
|
+
warnedTables.add(tblId);
|
|
22300
|
+
console.warn(`[kordoc] format profile: table ${tp.rows}x${tp.cols} vs document ${rowCnt}x${colCnt} \u2014 \uD504\uB85C\uD544 \uBB34\uC2DC`);
|
|
22301
|
+
}
|
|
22302
|
+
function usableProfile(tp, tblId, rowCnt, colCnt) {
|
|
22303
|
+
if (!tp) return null;
|
|
22304
|
+
if (tp.rows !== rowCnt || tp.cols !== colCnt) {
|
|
22305
|
+
warnProfileMismatch(tblId, tp, rowCnt, colCnt);
|
|
22306
|
+
return null;
|
|
22307
|
+
}
|
|
22308
|
+
return tp;
|
|
22309
|
+
}
|
|
22310
|
+
function resolveColWidths(tp, colCnt, fallbackTotal) {
|
|
22311
|
+
if (tp?.colWidths && tp.colWidths.length === colCnt) return tp.colWidths;
|
|
22312
|
+
const w = tp?.width ? Math.floor(tp.width / colCnt) : Math.floor(fallbackTotal / colCnt);
|
|
22313
|
+
return Array(colCnt).fill(w);
|
|
22314
|
+
}
|
|
22315
|
+
function generateTable(rows, theme, tp = null) {
|
|
22147
22316
|
const rowCnt = rows.length;
|
|
22148
22317
|
const colCnt = Math.max(...rows.map((r) => r.length), 1);
|
|
22149
|
-
const cellW = Math.floor(44e3 / colCnt);
|
|
22150
22318
|
const cellH = 1500;
|
|
22151
|
-
const tblW = cellW * colCnt;
|
|
22152
|
-
const tblH = cellH * rowCnt;
|
|
22153
22319
|
const tblId = nextTableId();
|
|
22320
|
+
const prof = usableProfile(tp, tblId, rowCnt, colCnt);
|
|
22321
|
+
const colW = resolveColWidths(prof, colCnt, 44e3);
|
|
22322
|
+
const tblW = colW.reduce((a, b) => a + b, 0);
|
|
22323
|
+
const tblH = cellH * rowCnt;
|
|
22154
22324
|
const useHeaderStyle = theme.tableHeader !== theme.body || theme.tableHeaderBold;
|
|
22155
22325
|
const trElements = rows.map((row, rowIdx) => {
|
|
22156
22326
|
const cells = row.length < colCnt ? [...row, ...Array(colCnt - row.length).fill("")] : row;
|
|
22157
22327
|
const isHeaderRow = rowIdx === 0;
|
|
22158
22328
|
const headerCharPr = isHeaderRow && useHeaderStyle ? CHAR_TABLE_HEADER : CHAR_NORMAL;
|
|
22159
22329
|
const tdElements = cells.map((cell, colIdx) => {
|
|
22160
|
-
const
|
|
22330
|
+
const k = `${rowIdx},${colIdx}`;
|
|
22331
|
+
const bf = prof?.cellBf.get(k) ?? 2;
|
|
22332
|
+
const ch = prof?.cellChar.get(k) ?? headerCharPr;
|
|
22333
|
+
const h = prof?.cellH.get(k) ?? cellH;
|
|
22334
|
+
const runs = generateRuns(cell, ch);
|
|
22161
22335
|
const p = `<hp:p paraPrIDRef="0" styleIDRef="0">${runs}</hp:p>`;
|
|
22162
|
-
return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="
|
|
22336
|
+
return `<hp:tc name="" header="${isHeaderRow ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${p}</hp:subList><hp:cellAddr colAddr="${colIdx}" rowAddr="${rowIdx}"/><hp:cellSpan colSpan="1" rowSpan="1"/><hp:cellSz width="${colW[colIdx]}" height="${h}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
22163
22337
|
}).join("");
|
|
22164
22338
|
return `<hp:tr>${tdElements}</hp:tr>`;
|
|
22165
22339
|
}).join("");
|
|
@@ -22190,35 +22364,42 @@ function layoutHtmlRows(rows) {
|
|
|
22190
22364
|
function unescapeHtml(s) {
|
|
22191
22365
|
return s.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&");
|
|
22192
22366
|
}
|
|
22193
|
-
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3) {
|
|
22367
|
+
function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3, tp = null) {
|
|
22194
22368
|
const rows = parseHtmlTable(rawHtml);
|
|
22195
22369
|
if (!rows || rows.length === 0) return null;
|
|
22196
22370
|
const { placed, rowCnt, colCnt } = layoutHtmlRows(rows);
|
|
22197
22371
|
if (rowCnt === 0 || colCnt === 0) return null;
|
|
22198
|
-
const colW = Math.floor(totalWidth / colCnt);
|
|
22199
22372
|
const cellH = 1500;
|
|
22200
|
-
const tblW = colW * colCnt;
|
|
22201
22373
|
const tblId = nextTableId();
|
|
22374
|
+
const prof = usableProfile(tp, tblId, rowCnt, colCnt);
|
|
22375
|
+
const colW = resolveColWidths(prof, colCnt, totalWidth);
|
|
22376
|
+
const tblW = colW.reduce((a, b) => a + b, 0);
|
|
22202
22377
|
const useHeaderStyle = theme.tableHeader !== theme.body || theme.tableHeaderBold;
|
|
22378
|
+
const spanW = (c, colSpan) => colW.slice(c, c + colSpan).reduce((a, b) => a + b, 0);
|
|
22203
22379
|
const tcXmls = placed.map((cell) => {
|
|
22380
|
+
const k = `${cell.r},${cell.c}`;
|
|
22381
|
+
const bf = prof?.cellBf.get(k) ?? 2;
|
|
22204
22382
|
const headerCharPr = cell.isHeader && useHeaderStyle ? CHAR_TABLE_HEADER : CHAR_NORMAL;
|
|
22383
|
+
const ch = prof?.cellChar.get(k) ?? headerCharPr;
|
|
22205
22384
|
const { lines } = htmlCellInnerToLines(cell.inner);
|
|
22206
22385
|
const paras = lines.map(
|
|
22207
|
-
(line) => `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${
|
|
22386
|
+
(line) => `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${ch}"><hp:t>${escapeXml(unescapeHtml(line))}</hp:t></hp:run></hp:p>`
|
|
22208
22387
|
);
|
|
22388
|
+
const cellW = spanW(cell.c, cell.colSpan);
|
|
22209
22389
|
let nestedH = 0;
|
|
22210
22390
|
for (const nested of extractTopLevelTables(cell.inner)) {
|
|
22211
|
-
const nestedXml = generateHtmlTableXml(nested, theme, Math.max(
|
|
22391
|
+
const nestedXml = generateHtmlTableXml(nested, theme, Math.max(cellW - 1020, 4e3));
|
|
22212
22392
|
if (nestedXml) {
|
|
22213
22393
|
paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${nestedXml}</hp:run></hp:p>`);
|
|
22214
22394
|
nestedH += (nested.match(/<tr[\s>]/gi) ?? []).length * cellH + 300;
|
|
22215
22395
|
}
|
|
22216
22396
|
}
|
|
22217
22397
|
if (paras.length === 0) {
|
|
22218
|
-
paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${
|
|
22398
|
+
paras.push(`<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="${ch}"><hp:t></hp:t></hp:run></hp:p>`);
|
|
22219
22399
|
}
|
|
22220
|
-
const
|
|
22221
|
-
|
|
22400
|
+
const contentH = Math.max(cellH * cell.rowSpan, Math.max(lines.length, 1) * 800 + nestedH);
|
|
22401
|
+
const cellHeight = Math.max(prof?.cellH.get(k) ?? 0, contentH);
|
|
22402
|
+
return `<hp:tc name="" header="${cell.isHeader ? 1 : 0}" hasMargin="0" protect="0" editable="1" dirty="0" borderFillIDRef="${bf}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">${paras.join("")}</hp:subList><hp:cellAddr colAddr="${cell.c}" rowAddr="${cell.r}"/><hp:cellSpan colSpan="${cell.colSpan}" rowSpan="${cell.rowSpan}"/><hp:cellSz width="${cellW}" height="${cellHeight}"/><hp:cellMargin left="141" right="141" top="141" bottom="141"/></hp:tc>`;
|
|
22222
22403
|
});
|
|
22223
22404
|
const trXmls = [];
|
|
22224
22405
|
for (let r = 0; r < rowCnt; r++) {
|
|
@@ -22384,9 +22565,9 @@ function readCommand(input, idx, depth) {
|
|
|
22384
22565
|
const command = name.value;
|
|
22385
22566
|
if (command === "\\") return { value: "#", next: name.next };
|
|
22386
22567
|
if (command === "frac") {
|
|
22387
|
-
const
|
|
22388
|
-
const den = readGroupOrToken(input,
|
|
22389
|
-
return { value: `{${
|
|
22568
|
+
const num4 = readGroupOrToken(input, name.next, depth);
|
|
22569
|
+
const den = readGroupOrToken(input, num4.next, depth);
|
|
22570
|
+
return { value: `{${num4.value}} over {${den.value}}`, next: den.next };
|
|
22390
22571
|
}
|
|
22391
22572
|
if (command === "sqrt") {
|
|
22392
22573
|
let cursor = skipSpaces(input, name.next);
|
|
@@ -22517,9 +22698,10 @@ function generateSecPr(gongmun) {
|
|
|
22517
22698
|
} : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
|
|
22518
22699
|
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>`;
|
|
22519
22700
|
}
|
|
22520
|
-
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null) {
|
|
22701
|
+
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null, chartParts = null, remap = null) {
|
|
22521
22702
|
const paraXmls = [];
|
|
22522
22703
|
let isFirst = true;
|
|
22704
|
+
let tableSeq = 0;
|
|
22523
22705
|
const orderedCounters = {};
|
|
22524
22706
|
let prevWasOrdered = false;
|
|
22525
22707
|
for (let blockIdx = 0; blockIdx < blocks.length; blockIdx++) {
|
|
@@ -22627,11 +22809,12 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22627
22809
|
paraXmls.push(`<hp:p paraPrIDRef="0" styleIDRef="0">${secRun}</hp:p>`);
|
|
22628
22810
|
isFirst = false;
|
|
22629
22811
|
}
|
|
22630
|
-
xml = generateTable(block.rows, theme);
|
|
22812
|
+
xml = generateTable(block.rows, theme, remap?.tables.get(tableSeq) ?? null);
|
|
22813
|
+
tableSeq++;
|
|
22631
22814
|
}
|
|
22632
22815
|
break;
|
|
22633
22816
|
case "html_table": {
|
|
22634
|
-
const tbl = generateHtmlTableXml(block.text || "", theme);
|
|
22817
|
+
const tbl = generateHtmlTableXml(block.text || "", theme, 44e3, remap?.tables.get(tableSeq) ?? null);
|
|
22635
22818
|
if (tbl) {
|
|
22636
22819
|
if (isFirst) {
|
|
22637
22820
|
const secRun = `<hp:run charPrIDRef="0">${generateSecPr(gongmun)}<hp:t></hp:t></hp:run>`;
|
|
@@ -22639,6 +22822,7 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22639
22822
|
isFirst = false;
|
|
22640
22823
|
}
|
|
22641
22824
|
xml = `<hp:p paraPrIDRef="0" styleIDRef="0"><hp:run charPrIDRef="0">${tbl}</hp:run></hp:p>`;
|
|
22825
|
+
tableSeq++;
|
|
22642
22826
|
} else {
|
|
22643
22827
|
const plain = (block.text || "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
22644
22828
|
xml = plain ? generateParagraph(plain) : "";
|
|
@@ -22665,6 +22849,93 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
22665
22849
|
</hs:sec>`;
|
|
22666
22850
|
}
|
|
22667
22851
|
|
|
22852
|
+
// src/hwpx/gen-profile.ts
|
|
22853
|
+
function parseHu(s) {
|
|
22854
|
+
if (s == null) return void 0;
|
|
22855
|
+
const n = parseInt(String(s).trim(), 10);
|
|
22856
|
+
return Number.isFinite(n) ? n : void 0;
|
|
22857
|
+
}
|
|
22858
|
+
function edgeXml(tag, d) {
|
|
22859
|
+
return d ? `<hh:${tag} type="${d.type}" width="${d.width}" color="${d.color}"/>` : `<hh:${tag} type="NONE" width="0.1 mm" color="#000000"/>`;
|
|
22860
|
+
}
|
|
22861
|
+
function borderFillDefToXml(id, def) {
|
|
22862
|
+
const fill = def.fill?.faceColor ? `<hh:fillBrush><hh:winBrush faceColor="${def.fill.faceColor}" hatchColor="#000000" alpha="0"/></hh:fillBrush>` : "";
|
|
22863
|
+
return ` <hh:borderFill id="${id}" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
22864
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
22865
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
22866
|
+
${edgeXml("leftBorder", def.leftBorder)}
|
|
22867
|
+
${edgeXml("rightBorder", def.rightBorder)}
|
|
22868
|
+
${edgeXml("topBorder", def.topBorder)}
|
|
22869
|
+
${edgeXml("bottomBorder", def.bottomBorder)}${fill ? `
|
|
22870
|
+
${fill}` : ""}
|
|
22871
|
+
</hh:borderFill>`;
|
|
22872
|
+
}
|
|
22873
|
+
function profileCharPrXml(id, def) {
|
|
22874
|
+
const height = parseHu(def.height_hwpunit) ?? 1e3;
|
|
22875
|
+
const color = def.textColor ?? "#000000";
|
|
22876
|
+
const font = def.fontRef_hangul != null ? parseInt(def.fontRef_hangul, 10) || 0 : 0;
|
|
22877
|
+
const boldAttr = def.bold ? ` bold="1"` : "";
|
|
22878
|
+
const italicAttr = def.italic ? ` italic="1"` : "";
|
|
22879
|
+
const underline = def.underline ? `
|
|
22880
|
+
<hh:underline type="BOTTOM" shape="SOLID" color="${color}"/>` : "";
|
|
22881
|
+
return ` <hh:charPr id="${id}" height="${height}" textColor="${color}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
22882
|
+
<hh:fontRef hangul="${font}" latin="${font}" hanja="${font}" japanese="${font}" other="${font}" symbol="${font}" user="${font}"/>
|
|
22883
|
+
<hh:ratio hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
22884
|
+
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
22885
|
+
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
22886
|
+
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>${underline}
|
|
22887
|
+
</hh:charPr>`;
|
|
22888
|
+
}
|
|
22889
|
+
function buildProfileRemap(profile, charPrBase, borderFillBase = 3) {
|
|
22890
|
+
const remap = { borderFillXmls: [], charPrXmls: [], tables: /* @__PURE__ */ new Map() };
|
|
22891
|
+
let bfNext = borderFillBase;
|
|
22892
|
+
let charNext = charPrBase;
|
|
22893
|
+
for (const t of profile.tables) {
|
|
22894
|
+
const localBf = {};
|
|
22895
|
+
for (const [key, def] of Object.entries(t.used_border_fills ?? {})) {
|
|
22896
|
+
const gid = bfNext++;
|
|
22897
|
+
remap.borderFillXmls.push(borderFillDefToXml(gid, def));
|
|
22898
|
+
localBf[key] = gid;
|
|
22899
|
+
}
|
|
22900
|
+
const localChar = {};
|
|
22901
|
+
for (const [key, def] of Object.entries(t.used_char_prs ?? {})) {
|
|
22902
|
+
const gid = charNext++;
|
|
22903
|
+
remap.charPrXmls.push(profileCharPrXml(gid, def));
|
|
22904
|
+
localChar[key] = gid;
|
|
22905
|
+
}
|
|
22906
|
+
let colWidths;
|
|
22907
|
+
if (t.col_widths_hwpunit && t.col_widths_hwpunit.length === t.cols) {
|
|
22908
|
+
const parsed = t.col_widths_hwpunit.map(parseHu);
|
|
22909
|
+
if (parsed.every((n) => n != null)) colWidths = parsed;
|
|
22910
|
+
}
|
|
22911
|
+
const tr = {
|
|
22912
|
+
rows: t.rows,
|
|
22913
|
+
cols: t.cols,
|
|
22914
|
+
width: parseHu(t.width_hwpunit),
|
|
22915
|
+
colWidths,
|
|
22916
|
+
cellBf: /* @__PURE__ */ new Map(),
|
|
22917
|
+
cellChar: /* @__PURE__ */ new Map(),
|
|
22918
|
+
cellH: /* @__PURE__ */ new Map()
|
|
22919
|
+
};
|
|
22920
|
+
for (const cell of t.cells) {
|
|
22921
|
+
const k = `${cell.row},${cell.col}`;
|
|
22922
|
+
if (cell.borderFillIDRef != null && cell.borderFillIDRef in localBf) {
|
|
22923
|
+
tr.cellBf.set(k, localBf[cell.borderFillIDRef]);
|
|
22924
|
+
}
|
|
22925
|
+
if (cell.charPrIDRef != null && cell.charPrIDRef in localChar) {
|
|
22926
|
+
tr.cellChar.set(k, localChar[cell.charPrIDRef]);
|
|
22927
|
+
}
|
|
22928
|
+
const h = parseHu(cell.height_hwpunit);
|
|
22929
|
+
if (h != null) tr.cellH.set(k, h);
|
|
22930
|
+
}
|
|
22931
|
+
remap.tables.set(t.table_index, tr);
|
|
22932
|
+
}
|
|
22933
|
+
return remap;
|
|
22934
|
+
}
|
|
22935
|
+
function profileCharPrBase(ratioVariantCount) {
|
|
22936
|
+
return CHAR_VARIANT_BASE + ratioVariantCount * 4;
|
|
22937
|
+
}
|
|
22938
|
+
|
|
22668
22939
|
// src/hwpx/generator.ts
|
|
22669
22940
|
async function markdownToHwpx(markdown, options) {
|
|
22670
22941
|
const theme = resolveTheme(options?.theme);
|
|
@@ -22672,13 +22943,14 @@ async function markdownToHwpx(markdown, options) {
|
|
|
22672
22943
|
const blocks = parseMarkdownToBlocks(markdown);
|
|
22673
22944
|
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
22674
22945
|
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
22946
|
+
const remap = options?.profile ? buildProfileRemap(options.profile, profileCharPrBase(fit?.variants?.length ?? 0)) : null;
|
|
22675
22947
|
const chartParts = [];
|
|
22676
|
-
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts);
|
|
22948
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit, chartParts, remap);
|
|
22677
22949
|
const zip = new JSZip7();
|
|
22678
22950
|
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
22679
22951
|
zip.file("META-INF/container.xml", generateContainerXml());
|
|
22680
22952
|
zip.file("Contents/content.hpf", generateManifest(chartParts));
|
|
22681
|
-
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? []));
|
|
22953
|
+
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? [], remap));
|
|
22682
22954
|
zip.file("Contents/section0.xml", sectionXml);
|
|
22683
22955
|
for (const part of chartParts) zip.file(part.name, part.xml);
|
|
22684
22956
|
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
@@ -22833,6 +23105,77 @@ var DEFAULT_PARA_GEOM = {
|
|
|
22833
23105
|
spaceAfter: 0
|
|
22834
23106
|
};
|
|
22835
23107
|
var DEFAULT_CHAR = { height: 1e3, bold: false, italic: false, underline: false, ratio: 100, spacing: 0 };
|
|
23108
|
+
var FONT_ALIASES = {
|
|
23109
|
+
"\uD568\uCD08\uB86C\uBC14\uD0D5": "'HCR Batang','\uD568\uCD08\uB86C\uBC14\uD0D5','\uD55C\uCEF4\uBC14\uD0D5'",
|
|
23110
|
+
"\uD55C\uCEF4\uBC14\uD0D5": "'HCR Batang','\uD568\uCD08\uB86C\uBC14\uD0D5','\uD55C\uCEF4\uBC14\uD0D5'",
|
|
23111
|
+
"\uD568\uCD08\uB86C\uB3CB\uC6C0": "'HCR Dotum','\uD568\uCD08\uB86C\uB3CB\uC6C0','\uD55C\uCEF4\uB3CB\uC6C0'",
|
|
23112
|
+
"\uD55C\uCEF4\uB3CB\uC6C0": "'HCR Dotum','\uD568\uCD08\uB86C\uB3CB\uC6C0','\uD55C\uCEF4\uB3CB\uC6C0'",
|
|
23113
|
+
"\uB9D1\uC740 \uACE0\uB515": "'Malgun Gothic','\uB9D1\uC740 \uACE0\uB515'",
|
|
23114
|
+
"\uB9D1\uC740\uACE0\uB515": "'Malgun Gothic','\uB9D1\uC740 \uACE0\uB515'",
|
|
23115
|
+
"\uAD74\uB9BC": "'Gulim','\uAD74\uB9BC'",
|
|
23116
|
+
"\uAD74\uB9BC\uCCB4": "'GulimChe','\uAD74\uB9BC\uCCB4','Gulim'",
|
|
23117
|
+
"\uB3CB\uC6C0": "'Dotum','\uB3CB\uC6C0'",
|
|
23118
|
+
"\uB3CB\uC6C0\uCCB4": "'DotumChe','\uB3CB\uC6C0\uCCB4','Dotum'",
|
|
23119
|
+
"\uBC14\uD0D5": "'Batang','\uBC14\uD0D5'",
|
|
23120
|
+
"\uBC14\uD0D5\uCCB4": "'BatangChe','\uBC14\uD0D5\uCCB4','Batang'",
|
|
23121
|
+
"\uAD81\uC11C": "'Gungsuh','\uAD81\uC11C'",
|
|
23122
|
+
"\uAD81\uC11C\uCCB4": "'GungsuhChe','\uAD81\uC11C\uCCB4','Gungsuh'",
|
|
23123
|
+
"\uB098\uB214\uACE0\uB515": "'NanumGothic','\uB098\uB214\uACE0\uB515'",
|
|
23124
|
+
"\uB098\uB214\uBA85\uC870": "'NanumMyeongjo','\uB098\uB214\uBA85\uC870'",
|
|
23125
|
+
"\uB9D1\uC740 \uACE0\uB515 Semilight": "'Malgun Gothic Semilight','\uB9D1\uC740 \uACE0\uB515'"
|
|
23126
|
+
};
|
|
23127
|
+
function isSerifFace(face) {
|
|
23128
|
+
return /바탕|명조|Batang|Myeong|Mincho|궁서|Gungsuh|Serif|신명|순명|Song|송/i.test(face);
|
|
23129
|
+
}
|
|
23130
|
+
function cssQuote(name) {
|
|
23131
|
+
return /^[A-Za-z0-9_-]+$/.test(name) ? name : `'${name.replace(/['"\\]/g, "")}'`;
|
|
23132
|
+
}
|
|
23133
|
+
function hwpFaceToCssStack(face) {
|
|
23134
|
+
const trimmed = (face ?? "").trim();
|
|
23135
|
+
if (!trimmed) return "";
|
|
23136
|
+
const generic = isSerifFace(trimmed) ? "'HCR Batang','Batang','Noto Serif KR',serif" : "'Malgun Gothic','HCR Dotum','Noto Sans KR',sans-serif";
|
|
23137
|
+
const head = FONT_ALIASES[trimmed] ?? cssQuote(trimmed);
|
|
23138
|
+
return `${head},${generic}`;
|
|
23139
|
+
}
|
|
23140
|
+
function collectHangulFonts(root) {
|
|
23141
|
+
const map = /* @__PURE__ */ new Map();
|
|
23142
|
+
const findFaces = (el, depth) => {
|
|
23143
|
+
if (depth > 24) return null;
|
|
23144
|
+
for (const ch of Array.from(el.childNodes)) {
|
|
23145
|
+
if (ch.nodeType !== 1) continue;
|
|
23146
|
+
const e = ch;
|
|
23147
|
+
if ((e.tagName || "").replace(/^[^:]+:/, "") === "fontfaces") return e;
|
|
23148
|
+
const f = findFaces(e, depth + 1);
|
|
23149
|
+
if (f) return f;
|
|
23150
|
+
}
|
|
23151
|
+
return null;
|
|
23152
|
+
};
|
|
23153
|
+
const faces = findFaces(root, 0);
|
|
23154
|
+
if (!faces) return map;
|
|
23155
|
+
let group = null;
|
|
23156
|
+
let firstGroup = null;
|
|
23157
|
+
for (const ch of Array.from(faces.childNodes)) {
|
|
23158
|
+
if (ch.nodeType !== 1) continue;
|
|
23159
|
+
const e = ch;
|
|
23160
|
+
if ((e.tagName || "").replace(/^[^:]+:/, "") !== "fontface") continue;
|
|
23161
|
+
if (!firstGroup) firstGroup = e;
|
|
23162
|
+
if ((e.getAttribute("lang") ?? "").toUpperCase() === "HANGUL") {
|
|
23163
|
+
group = e;
|
|
23164
|
+
break;
|
|
23165
|
+
}
|
|
23166
|
+
}
|
|
23167
|
+
group = group ?? firstGroup;
|
|
23168
|
+
if (!group) return map;
|
|
23169
|
+
for (const ch of Array.from(group.childNodes)) {
|
|
23170
|
+
if (ch.nodeType !== 1) continue;
|
|
23171
|
+
const e = ch;
|
|
23172
|
+
if ((e.tagName || "").replace(/^[^:]+:/, "") !== "font") continue;
|
|
23173
|
+
const id = e.getAttribute("id");
|
|
23174
|
+
const face = e.getAttribute("face");
|
|
23175
|
+
if (id != null && face) map.set(id, face);
|
|
23176
|
+
}
|
|
23177
|
+
return map;
|
|
23178
|
+
}
|
|
22836
23179
|
function borderWidthPt(v) {
|
|
22837
23180
|
const n = parseFloat(v ?? "");
|
|
22838
23181
|
if (!Number.isFinite(n)) return 0.34;
|
|
@@ -22884,6 +23227,7 @@ function parseRenderStyles(headXml) {
|
|
|
22884
23227
|
const doc = createXmlParser().parseFromString(headXml, "text/xml");
|
|
22885
23228
|
const root = doc.documentElement;
|
|
22886
23229
|
if (!root) return styles;
|
|
23230
|
+
const hangulFonts = collectHangulFonts(root);
|
|
22887
23231
|
const walk = (el) => {
|
|
22888
23232
|
const tag = (el.tagName || "").replace(/^[^:]+:/, "");
|
|
22889
23233
|
if (tag === "charPr") {
|
|
@@ -22893,6 +23237,9 @@ function parseRenderStyles(headXml) {
|
|
|
22893
23237
|
const spacingEl = findChildByLocalName(el, "spacing");
|
|
22894
23238
|
const underlineEl = findChildByLocalName(el, "underline");
|
|
22895
23239
|
const textColor = el.getAttribute("textColor");
|
|
23240
|
+
const fontRef = findChildByLocalName(el, "fontRef");
|
|
23241
|
+
const fontId = fontRef?.getAttribute("hangul") ?? fontRef?.getAttribute("latin");
|
|
23242
|
+
const face = fontId != null ? hangulFonts.get(fontId) : void 0;
|
|
22896
23243
|
styles.charPr.set(id, {
|
|
22897
23244
|
height: Number(el.getAttribute("height")) || 1e3,
|
|
22898
23245
|
bold: findChildByLocalName(el, "bold") != null,
|
|
@@ -22900,7 +23247,8 @@ function parseRenderStyles(headXml) {
|
|
|
22900
23247
|
underline: underlineEl != null && (underlineEl.getAttribute("type") ?? "NONE") !== "NONE",
|
|
22901
23248
|
color: textColor && textColor !== "#000000" && textColor.toLowerCase() !== "none" ? textColor : void 0,
|
|
22902
23249
|
ratio: Number(ratioEl?.getAttribute("hangul")) || 100,
|
|
22903
|
-
spacing: Number(spacingEl?.getAttribute("hangul")) || 0
|
|
23250
|
+
spacing: Number(spacingEl?.getAttribute("hangul")) || 0,
|
|
23251
|
+
fontFamily: face ? hwpFaceToCssStack(face) : void 0
|
|
22904
23252
|
});
|
|
22905
23253
|
}
|
|
22906
23254
|
} else if (tag === "paraPr") {
|
|
@@ -23234,8 +23582,186 @@ async function placeSealHwpx(hwpxBuffer, ops) {
|
|
|
23234
23582
|
};
|
|
23235
23583
|
}
|
|
23236
23584
|
|
|
23237
|
-
// src/
|
|
23585
|
+
// src/hwpx/extract-profile.ts
|
|
23238
23586
|
import JSZip9 from "jszip";
|
|
23587
|
+
function elemsByLocal(root, name) {
|
|
23588
|
+
const all = root.getElementsByTagName("*");
|
|
23589
|
+
const out = [];
|
|
23590
|
+
for (let i = 0; i < all.length; i++) {
|
|
23591
|
+
const el = all[i];
|
|
23592
|
+
const tag = (el.tagName || el.localName || "").replace(/^[^:]+:/, "");
|
|
23593
|
+
if (tag === name) out.push(el);
|
|
23594
|
+
}
|
|
23595
|
+
return out;
|
|
23596
|
+
}
|
|
23597
|
+
function borderDefOf(el) {
|
|
23598
|
+
if (!el) return void 0;
|
|
23599
|
+
const type = el.getAttribute("type") || "NONE";
|
|
23600
|
+
const width = el.getAttribute("width") || "0.1 mm";
|
|
23601
|
+
const color = el.getAttribute("color") || "#000000";
|
|
23602
|
+
return { type, width, color };
|
|
23603
|
+
}
|
|
23604
|
+
function parseBorderFills(headerDoc) {
|
|
23605
|
+
const map = /* @__PURE__ */ new Map();
|
|
23606
|
+
for (const bf of elemsByLocal(headerDoc, "borderFill")) {
|
|
23607
|
+
const id = bf.getAttribute("id");
|
|
23608
|
+
if (!id) continue;
|
|
23609
|
+
const def = {
|
|
23610
|
+
leftBorder: borderDefOf(findChildByLocalName(bf, "leftBorder")),
|
|
23611
|
+
rightBorder: borderDefOf(findChildByLocalName(bf, "rightBorder")),
|
|
23612
|
+
topBorder: borderDefOf(findChildByLocalName(bf, "topBorder")),
|
|
23613
|
+
bottomBorder: borderDefOf(findChildByLocalName(bf, "bottomBorder"))
|
|
23614
|
+
};
|
|
23615
|
+
const fillBrush = findChildByLocalName(bf, "fillBrush");
|
|
23616
|
+
const winBrush = fillBrush ? findChildByLocalName(fillBrush, "winBrush") : null;
|
|
23617
|
+
const face = winBrush?.getAttribute("faceColor");
|
|
23618
|
+
if (face && face !== "none") def.fill = { faceColor: face };
|
|
23619
|
+
map.set(id, def);
|
|
23620
|
+
}
|
|
23621
|
+
return map;
|
|
23622
|
+
}
|
|
23623
|
+
function parseCharPrs(headerDoc) {
|
|
23624
|
+
const map = /* @__PURE__ */ new Map();
|
|
23625
|
+
for (const cp of elemsByLocal(headerDoc, "charPr")) {
|
|
23626
|
+
const id = cp.getAttribute("id");
|
|
23627
|
+
if (!id) continue;
|
|
23628
|
+
const def = {};
|
|
23629
|
+
const h = cp.getAttribute("height");
|
|
23630
|
+
if (h) def.height_hwpunit = h;
|
|
23631
|
+
const color = cp.getAttribute("textColor");
|
|
23632
|
+
if (color) def.textColor = color;
|
|
23633
|
+
if (cp.getAttribute("bold") === "1") def.bold = true;
|
|
23634
|
+
if (cp.getAttribute("italic") === "1") def.italic = true;
|
|
23635
|
+
if (findChildByLocalName(cp, "underline")) def.underline = true;
|
|
23636
|
+
const fontRef = findChildByLocalName(cp, "fontRef");
|
|
23637
|
+
const hangul = fontRef?.getAttribute("hangul");
|
|
23638
|
+
if (hangul) def.fontRef_hangul = hangul;
|
|
23639
|
+
map.set(id, def);
|
|
23640
|
+
}
|
|
23641
|
+
return map;
|
|
23642
|
+
}
|
|
23643
|
+
function isTopLevelTable(tbl) {
|
|
23644
|
+
let p = tbl.parentNode;
|
|
23645
|
+
while (p) {
|
|
23646
|
+
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
23647
|
+
if (tag === "tbl") return false;
|
|
23648
|
+
p = p.parentNode;
|
|
23649
|
+
}
|
|
23650
|
+
return true;
|
|
23651
|
+
}
|
|
23652
|
+
function num(s) {
|
|
23653
|
+
if (s == null) return void 0;
|
|
23654
|
+
const n = parseInt(s, 10);
|
|
23655
|
+
return Number.isFinite(n) ? n : void 0;
|
|
23656
|
+
}
|
|
23657
|
+
function parseTable3(tbl, tableIndex, borderFills, charPrs) {
|
|
23658
|
+
const rows = num(tbl.getAttribute("rowCnt")) ?? 0;
|
|
23659
|
+
const cols = num(tbl.getAttribute("colCnt")) ?? 0;
|
|
23660
|
+
const sz = findChildByLocalName(tbl, "sz");
|
|
23661
|
+
const width = sz?.getAttribute("width") || void 0;
|
|
23662
|
+
const cells = [];
|
|
23663
|
+
const usedBf = /* @__PURE__ */ new Set();
|
|
23664
|
+
const usedCp = /* @__PURE__ */ new Set();
|
|
23665
|
+
const colWidths = new Array(cols).fill(void 0);
|
|
23666
|
+
for (const tc of elemsByLocal(tbl, "tc")) {
|
|
23667
|
+
if (nearestTable(tc) !== tbl) continue;
|
|
23668
|
+
const addr = findChildByLocalName(tc, "cellAddr");
|
|
23669
|
+
const span = findChildByLocalName(tc, "cellSpan");
|
|
23670
|
+
const csz = findChildByLocalName(tc, "cellSz");
|
|
23671
|
+
const row = num(addr?.getAttribute("rowAddr")) ?? 0;
|
|
23672
|
+
const col = num(addr?.getAttribute("colAddr")) ?? 0;
|
|
23673
|
+
const colSpan = num(span?.getAttribute("colSpan")) ?? 1;
|
|
23674
|
+
const rowSpan = num(span?.getAttribute("rowSpan")) ?? 1;
|
|
23675
|
+
const bfId = tc.getAttribute("borderFillIDRef") || void 0;
|
|
23676
|
+
const cpId = firstRunCharPr(tc);
|
|
23677
|
+
const cell = { row, col, rowSpan, colSpan };
|
|
23678
|
+
const w = csz?.getAttribute("width");
|
|
23679
|
+
const hh = csz?.getAttribute("height");
|
|
23680
|
+
if (w) cell.width_hwpunit = w;
|
|
23681
|
+
if (hh) cell.height_hwpunit = hh;
|
|
23682
|
+
if (bfId) {
|
|
23683
|
+
cell.borderFillIDRef = bfId;
|
|
23684
|
+
usedBf.add(bfId);
|
|
23685
|
+
}
|
|
23686
|
+
if (cpId) {
|
|
23687
|
+
cell.charPrIDRef = cpId;
|
|
23688
|
+
usedCp.add(cpId);
|
|
23689
|
+
}
|
|
23690
|
+
cells.push(cell);
|
|
23691
|
+
if (row === 0 && colSpan === 1 && col < cols && w) colWidths[col] = w;
|
|
23692
|
+
}
|
|
23693
|
+
const table = {
|
|
23694
|
+
table_index: tableIndex,
|
|
23695
|
+
rows,
|
|
23696
|
+
cols,
|
|
23697
|
+
cells,
|
|
23698
|
+
used_border_fills: pick(borderFills, usedBf)
|
|
23699
|
+
};
|
|
23700
|
+
if (width) table.width_hwpunit = width;
|
|
23701
|
+
if (colWidths.every((w) => w != null)) table.col_widths_hwpunit = colWidths;
|
|
23702
|
+
const cp = pick(charPrs, usedCp);
|
|
23703
|
+
if (Object.keys(cp).length) table.used_char_prs = cp;
|
|
23704
|
+
return table;
|
|
23705
|
+
}
|
|
23706
|
+
function nearestTable(tc) {
|
|
23707
|
+
let p = tc.parentNode;
|
|
23708
|
+
while (p) {
|
|
23709
|
+
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
23710
|
+
if (tag === "tbl") return p;
|
|
23711
|
+
p = p.parentNode;
|
|
23712
|
+
}
|
|
23713
|
+
return null;
|
|
23714
|
+
}
|
|
23715
|
+
function firstRunCharPr(tc) {
|
|
23716
|
+
for (const run of elemsByLocal(tc, "run")) {
|
|
23717
|
+
if (nearestCell(run) !== tc) continue;
|
|
23718
|
+
const id = run.getAttribute("charPrIDRef");
|
|
23719
|
+
if (id) return id;
|
|
23720
|
+
}
|
|
23721
|
+
return void 0;
|
|
23722
|
+
}
|
|
23723
|
+
function nearestCell(el) {
|
|
23724
|
+
let p = el.parentNode;
|
|
23725
|
+
while (p) {
|
|
23726
|
+
const tag = (p.tagName || p.localName || "").replace(/^[^:]+:/, "");
|
|
23727
|
+
if (tag === "tc") return p;
|
|
23728
|
+
p = p.parentNode;
|
|
23729
|
+
}
|
|
23730
|
+
return null;
|
|
23731
|
+
}
|
|
23732
|
+
function pick(map, keys) {
|
|
23733
|
+
const out = {};
|
|
23734
|
+
for (const k of keys) {
|
|
23735
|
+
const v = map.get(k);
|
|
23736
|
+
if (v !== void 0) out[k] = v;
|
|
23737
|
+
}
|
|
23738
|
+
return out;
|
|
23739
|
+
}
|
|
23740
|
+
async function hwpxToProfile(input) {
|
|
23741
|
+
const buf = input instanceof ArrayBuffer ? input : toArrayBuffer(input);
|
|
23742
|
+
const zip = await JSZip9.loadAsync(buf);
|
|
23743
|
+
const parser = createXmlParser();
|
|
23744
|
+
const headerFile = zip.file("Contents/header.xml") ?? zip.file(/[Hh]eader\.xml$/)?.[0];
|
|
23745
|
+
let headerXml = "<root/>";
|
|
23746
|
+
if (headerFile) headerXml = await headerFile.async("text");
|
|
23747
|
+
const headerDoc = parser.parseFromString(headerXml, "text/xml");
|
|
23748
|
+
const borderFills = parseBorderFills(headerDoc);
|
|
23749
|
+
const charPrs = parseCharPrs(headerDoc);
|
|
23750
|
+
const sectionFiles = zip.file(/[Ss]ection\d+\.xml$/).sort((a, b) => (num(a.name.match(/(\d+)\.xml$/)?.[1] ?? null) ?? 0) - (num(b.name.match(/(\d+)\.xml$/)?.[1] ?? null) ?? 0));
|
|
23751
|
+
const tables = [];
|
|
23752
|
+
let tableIndex = 0;
|
|
23753
|
+
for (const f of sectionFiles) {
|
|
23754
|
+
const doc = parser.parseFromString(await f.async("text"), "text/xml");
|
|
23755
|
+
for (const tbl of elemsByLocal(doc, "tbl")) {
|
|
23756
|
+
if (!isTopLevelTable(tbl)) continue;
|
|
23757
|
+
tables.push(parseTable3(tbl, tableIndex++, borderFills, charPrs));
|
|
23758
|
+
}
|
|
23759
|
+
}
|
|
23760
|
+
return { schema_version: "0.1.0", tables };
|
|
23761
|
+
}
|
|
23762
|
+
|
|
23763
|
+
// src/roundtrip/patcher.ts
|
|
23764
|
+
import JSZip10 from "jszip";
|
|
23239
23765
|
|
|
23240
23766
|
// src/roundtrip/table-rows.ts
|
|
23241
23767
|
var ROW_OBJECT_RE = /<(?:[A-Za-z0-9_]+:)?(?:tbl|pic|equation|ole|container|shape|drawingObject|drawText|video|chart|fieldBegin|fieldEnd|ctrl)\b/;
|
|
@@ -23873,7 +24399,7 @@ async function patchHwpx(original, editedMarkdown, options) {
|
|
|
23873
24399
|
}
|
|
23874
24400
|
let zip;
|
|
23875
24401
|
try {
|
|
23876
|
-
zip = await
|
|
24402
|
+
zip = await JSZip10.loadAsync(original);
|
|
23877
24403
|
} catch {
|
|
23878
24404
|
return { success: false, applied: 0, skipped, error: "ZIP \uB85C\uB4DC \uC2E4\uD328" };
|
|
23879
24405
|
}
|
|
@@ -23964,16 +24490,16 @@ function buildOrigUnits(blocks) {
|
|
|
23964
24490
|
for (let i = 0; i < blocks.length; i++) {
|
|
23965
24491
|
const block = blocks[i];
|
|
23966
24492
|
let consume = 1;
|
|
23967
|
-
let
|
|
24493
|
+
let chunk2;
|
|
23968
24494
|
if (block.type === "paragraph" && block.text && /^\[별표\s*\d+/.test(sanitizeText(block.text))) {
|
|
23969
24495
|
const next = blocks[i + 1];
|
|
23970
24496
|
if (next?.type === "paragraph" && next.text && /관련\)?$/.test(next.text)) consume = 2;
|
|
23971
|
-
|
|
24497
|
+
chunk2 = blocksToMarkdown(blocks.slice(i, i + consume));
|
|
23972
24498
|
} else {
|
|
23973
|
-
|
|
24499
|
+
chunk2 = blocksToMarkdown([block]);
|
|
23974
24500
|
}
|
|
23975
|
-
if (
|
|
23976
|
-
const subUnits = splitMarkdownUnits(
|
|
24501
|
+
if (chunk2) {
|
|
24502
|
+
const subUnits = splitMarkdownUnits(chunk2);
|
|
23977
24503
|
const isFragment = consume === 2 || (block.type === "paragraph" || block.type === "heading") && subUnits.length > 1;
|
|
23978
24504
|
for (let s = 0; s < subUnits.length; s++) {
|
|
23979
24505
|
const u = { ...subUnits[s], blockIdx: i, fragment: isFragment || void 0 };
|
|
@@ -24807,19 +25333,19 @@ function resolveTableMappings(blocks, scanTables) {
|
|
|
24807
25333
|
if (scanTables[k].rows === table.rows && scanTables[k].cols === table.cols) cands.push(k);
|
|
24808
25334
|
}
|
|
24809
25335
|
if (cands.length === 0) continue;
|
|
24810
|
-
let
|
|
25336
|
+
let pick2 = cands[0];
|
|
24811
25337
|
if (cands.length > 1) {
|
|
24812
25338
|
let best = tableContentScore(table, scanTables[cands[0]]);
|
|
24813
25339
|
for (let ci = 1; ci < cands.length; ci++) {
|
|
24814
25340
|
const sc = tableContentScore(table, scanTables[cands[ci]]);
|
|
24815
25341
|
if (sc > best) {
|
|
24816
25342
|
best = sc;
|
|
24817
|
-
|
|
25343
|
+
pick2 = cands[ci];
|
|
24818
25344
|
}
|
|
24819
25345
|
}
|
|
24820
25346
|
}
|
|
24821
|
-
result.set(i, scanTables[
|
|
24822
|
-
si =
|
|
25347
|
+
result.set(i, scanTables[pick2]);
|
|
25348
|
+
si = pick2 + 1;
|
|
24823
25349
|
}
|
|
24824
25350
|
return result;
|
|
24825
25351
|
}
|
|
@@ -25295,7 +25821,7 @@ function stageParaPatch(scan, para, newPlain, skip) {
|
|
|
25295
25821
|
}
|
|
25296
25822
|
|
|
25297
25823
|
// src/validate.ts
|
|
25298
|
-
import
|
|
25824
|
+
import JSZip11 from "jszip";
|
|
25299
25825
|
import { DOMParser as DOMParser5 } from "@xmldom/xmldom";
|
|
25300
25826
|
var REQUIRED_FILES = [
|
|
25301
25827
|
"mimetype",
|
|
@@ -25313,7 +25839,7 @@ async function validateHwpx(buffer) {
|
|
|
25313
25839
|
const issues = [];
|
|
25314
25840
|
let zip;
|
|
25315
25841
|
try {
|
|
25316
|
-
zip = await
|
|
25842
|
+
zip = await JSZip11.loadAsync(buffer);
|
|
25317
25843
|
} catch (err) {
|
|
25318
25844
|
return {
|
|
25319
25845
|
ok: false,
|
|
@@ -25381,10 +25907,10 @@ async function validateHwpx(buffer) {
|
|
|
25381
25907
|
}
|
|
25382
25908
|
|
|
25383
25909
|
// src/roundtrip/session.ts
|
|
25384
|
-
import
|
|
25910
|
+
import JSZip12 from "jszip";
|
|
25385
25911
|
async function buildState(bytes) {
|
|
25386
25912
|
const parsed = await parseHwpxDocument(u8ToArrayBuffer2(bytes));
|
|
25387
|
-
const zip = await
|
|
25913
|
+
const zip = await JSZip12.loadAsync(bytes);
|
|
25388
25914
|
const sectionPaths = await resolveSectionEntryNames(zip);
|
|
25389
25915
|
if (sectionPaths.length === 0) {
|
|
25390
25916
|
throw new Error("HWPX \uC139\uC158 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
@@ -25879,7 +26405,7 @@ async function blocksToPdf(blocks, options) {
|
|
|
25879
26405
|
}
|
|
25880
26406
|
|
|
25881
26407
|
// src/render/svg-render.ts
|
|
25882
|
-
import
|
|
26408
|
+
import JSZip13 from "jszip";
|
|
25883
26409
|
|
|
25884
26410
|
// src/render/layout.ts
|
|
25885
26411
|
function toInt32(v, fallback = 0) {
|
|
@@ -25968,7 +26494,7 @@ function elements(el) {
|
|
|
25968
26494
|
for (let i = 0; i < kids2.length; i++) if (kids2[i].nodeType === 1) out.push(kids2[i]);
|
|
25969
26495
|
return out;
|
|
25970
26496
|
}
|
|
25971
|
-
function
|
|
26497
|
+
function num2(el, attr, fallback = 0) {
|
|
25972
26498
|
return el ? toInt32(el.getAttribute(attr) ?? void 0, fallback) : fallback;
|
|
25973
26499
|
}
|
|
25974
26500
|
function shiftParaVert(p, delta) {
|
|
@@ -25976,7 +26502,7 @@ function shiftParaVert(p, delta) {
|
|
|
25976
26502
|
if (ln(lsa) !== "linesegarray") continue;
|
|
25977
26503
|
for (const seg of elements(lsa)) {
|
|
25978
26504
|
if (ln(seg) !== "lineseg") continue;
|
|
25979
|
-
seg.setAttribute("vertpos", String(
|
|
26505
|
+
seg.setAttribute("vertpos", String(num2(seg, "vertpos") + delta));
|
|
25980
26506
|
}
|
|
25981
26507
|
}
|
|
25982
26508
|
}
|
|
@@ -26031,7 +26557,7 @@ function reflowPara(p, doc, styles, areaW, startV, mode) {
|
|
|
26031
26557
|
const lsa = doc.createElement("hp:linesegarray");
|
|
26032
26558
|
for (let li = 0; li < wrap.starts.length; li++) {
|
|
26033
26559
|
const startReal = wrap.starts[li];
|
|
26034
|
-
const textpos = startReal < realIdx.length ? realIdx[startReal] :
|
|
26560
|
+
const textpos = startReal < realIdx.length ? realIdx[startReal] : 0;
|
|
26035
26561
|
const vertpos = startV + li * pitch;
|
|
26036
26562
|
const isFirst = li === 0;
|
|
26037
26563
|
const seg = doc.createElement("hp:lineseg");
|
|
@@ -26066,9 +26592,9 @@ function reflowTablesIn(p, doc, styles, mode, counter) {
|
|
|
26066
26592
|
if (ln(tc) !== "tc") continue;
|
|
26067
26593
|
const csz = findChildByLocalName(tc, "cellSz");
|
|
26068
26594
|
const cm = findChildByLocalName(tc, "cellMargin");
|
|
26069
|
-
const cellW =
|
|
26070
|
-
const mL = cm ?
|
|
26071
|
-
const mR = cm ?
|
|
26595
|
+
const cellW = num2(csz, "width");
|
|
26596
|
+
const mL = cm ? num2(cm, "left", 141) : 141;
|
|
26597
|
+
const mR = cm ? num2(cm, "right", 141) : 141;
|
|
26072
26598
|
const areaW = Math.max(500, cellW - mL - mR);
|
|
26073
26599
|
const sub = findChildByLocalName(tc, "subList");
|
|
26074
26600
|
if (sub) reflowBlockFlow(sub, doc, styles, areaW, mode, counter, 0);
|
|
@@ -26119,7 +26645,7 @@ function elements2(el) {
|
|
|
26119
26645
|
}
|
|
26120
26646
|
return out;
|
|
26121
26647
|
}
|
|
26122
|
-
function
|
|
26648
|
+
function num3(el, attr, fallback = 0) {
|
|
26123
26649
|
return el ? toInt32(el.getAttribute(attr) ?? void 0, fallback) : fallback;
|
|
26124
26650
|
}
|
|
26125
26651
|
function findFirst(el, name, depth = 0) {
|
|
@@ -26187,8 +26713,8 @@ function buildPara(p) {
|
|
|
26187
26713
|
} else if (OBJ_TAGS.has(cn)) {
|
|
26188
26714
|
const sz = findChildByLocalName(ch, "sz");
|
|
26189
26715
|
const pos = findChildByLocalName(ch, "pos");
|
|
26190
|
-
const w =
|
|
26191
|
-
const h =
|
|
26716
|
+
const w = num3(sz, "width") || num3(findChildByLocalName(ch, "curSz"), "width") || num3(findChildByLocalName(ch, "orgSz"), "width");
|
|
26717
|
+
const h = num3(sz, "height") || num3(findChildByLocalName(ch, "curSz"), "height") || num3(findChildByLocalName(ch, "orgSz"), "height");
|
|
26192
26718
|
objs.push({
|
|
26193
26719
|
el: ch,
|
|
26194
26720
|
tag: cn,
|
|
@@ -26204,12 +26730,12 @@ function buildPara(p) {
|
|
|
26204
26730
|
}
|
|
26205
26731
|
} else if (tag === "linesegarray") {
|
|
26206
26732
|
segs = elements2(runEl).filter((s) => ln2(s) === "lineseg").map((s) => ({
|
|
26207
|
-
textpos:
|
|
26208
|
-
vertpos:
|
|
26209
|
-
horzpos:
|
|
26210
|
-
horzsize:
|
|
26211
|
-
textheight:
|
|
26212
|
-
baseline:
|
|
26733
|
+
textpos: num3(s, "textpos"),
|
|
26734
|
+
vertpos: num3(s, "vertpos"),
|
|
26735
|
+
horzpos: num3(s, "horzpos"),
|
|
26736
|
+
horzsize: num3(s, "horzsize"),
|
|
26737
|
+
textheight: num3(s, "textheight", 1e3),
|
|
26738
|
+
baseline: num3(s, "baseline", 850)
|
|
26213
26739
|
}));
|
|
26214
26740
|
}
|
|
26215
26741
|
}
|
|
@@ -26311,6 +26837,7 @@ function drawPara(p, ox, oy, areaW, ctx, depth, segPages) {
|
|
|
26311
26837
|
}
|
|
26312
26838
|
if (text.trim().length > 0) {
|
|
26313
26839
|
const attrs = [`x="${pt(cx)}"`, `y="${pt(y)}"`, `font-size="${pt(st.height)}"`];
|
|
26840
|
+
if (st.fontFamily) attrs.push(`font-family="${st.fontFamily}"`);
|
|
26314
26841
|
if ([...text].length > 1 && sw > 50) {
|
|
26315
26842
|
attrs.push(`textLength="${pt(sw)}"`, `lengthAdjust="${plan.scale < 1 ? "spacingAndGlyphs" : "spacing"}"`);
|
|
26316
26843
|
}
|
|
@@ -26378,11 +26905,11 @@ function anchorObject(o, ox, oy, baseV, areaW, ctx) {
|
|
|
26378
26905
|
const { PW, PH, ML, MT, BODY_W, BODY_H } = ctx.geom;
|
|
26379
26906
|
const pos = findChildByLocalName(o.el, "pos");
|
|
26380
26907
|
const om = findChildByLocalName(o.el, "outMargin");
|
|
26381
|
-
const omT =
|
|
26908
|
+
const omT = num3(om, "top"), omB = num3(om, "bottom");
|
|
26382
26909
|
const w = o.width, h = o.height;
|
|
26383
26910
|
if (!pos) return { x: ox, y: oy + baseV };
|
|
26384
|
-
const vo =
|
|
26385
|
-
const ho =
|
|
26911
|
+
const vo = num3(pos, "vertOffset");
|
|
26912
|
+
const ho = num3(pos, "horzOffset");
|
|
26386
26913
|
const vrel = pos.getAttribute("vertRelTo") ?? "PARA";
|
|
26387
26914
|
const hrel = pos.getAttribute("horzRelTo") ?? "PARA";
|
|
26388
26915
|
const va = pos.getAttribute("vertAlign") ?? "TOP";
|
|
@@ -26419,8 +26946,8 @@ function drawObject(o, x, y, baseV, areaW, ctx, depth) {
|
|
|
26419
26946
|
if (!OBJ_TAGS.has(tag)) continue;
|
|
26420
26947
|
const sz = findChildByLocalName(ch, "sz");
|
|
26421
26948
|
const off = findChildByLocalName(ch, "offset");
|
|
26422
|
-
const sub = { el: ch, tag, index: 0, inline: true, width:
|
|
26423
|
-
drawObject(sub, x +
|
|
26949
|
+
const sub = { el: ch, tag, index: 0, inline: true, width: num3(sz, "width"), height: num3(sz, "height") };
|
|
26950
|
+
drawObject(sub, x + num3(off, "x"), y + num3(off, "y"), baseV, areaW, ctx, depth + 1);
|
|
26424
26951
|
}
|
|
26425
26952
|
} else if (o.tag === "equation") {
|
|
26426
26953
|
warnOnce(ctx, "equation", "\uC218\uC2DD \uAC1C\uCCB4\uB294 \uB80C\uB354 \uBBF8\uC9C0\uC6D0 \u2014 \uC0DD\uB7B5");
|
|
@@ -26438,16 +26965,16 @@ function drawShape(o, x, y, ctx, depth) {
|
|
|
26438
26965
|
const el = o.el;
|
|
26439
26966
|
const orgSz = findChildByLocalName(el, "orgSz");
|
|
26440
26967
|
const curSz = findChildByLocalName(el, "curSz");
|
|
26441
|
-
const ow =
|
|
26442
|
-
const w =
|
|
26443
|
-
const h =
|
|
26968
|
+
const ow = num3(orgSz, "width"), oh = num3(orgSz, "height");
|
|
26969
|
+
const w = num3(curSz, "width") || ow || o.width;
|
|
26970
|
+
const h = num3(curSz, "height") || oh || o.height;
|
|
26444
26971
|
const sx = ow > 0 ? w / ow : 1;
|
|
26445
26972
|
const sy = oh > 0 ? h / oh : 1;
|
|
26446
26973
|
const lineShape = findChildByLocalName(el, "lineShape");
|
|
26447
26974
|
const lstyle = lineShape?.getAttribute("style") ?? "SOLID";
|
|
26448
26975
|
const strokeCol = lineShape?.getAttribute("color") || "#000000";
|
|
26449
26976
|
const hasStroke = lstyle !== "NONE";
|
|
26450
|
-
const strokeW = hasStroke ? shapeStrokePt(lineShape ?
|
|
26977
|
+
const strokeW = hasStroke ? shapeStrokePt(lineShape ? num3(lineShape, "width") : 33) : 0;
|
|
26451
26978
|
const dash = /DASH|DOT/.test(lstyle) ? ` stroke-dasharray="${lstyle.includes("DOT") ? "1,1.5" : "3,1.5"}"` : "";
|
|
26452
26979
|
const strokeAttr = hasStroke ? ` stroke="${escapeXml3(strokeCol)}" stroke-width="${strokeW.toFixed(2)}"${dash}` : "";
|
|
26453
26980
|
const fillBrush = findChildByLocalName(el, "fillBrush");
|
|
@@ -26461,12 +26988,12 @@ function drawShape(o, x, y, ctx, depth) {
|
|
|
26461
26988
|
emit(ctx, `<ellipse cx="${pt(x + w / 2)}" cy="${pt(y + h / 2)}" rx="${pt(w / 2)}" ry="${pt(h / 2)}"${fillAttr}${strokeAttr}/>`);
|
|
26462
26989
|
} else if (o.tag === "line") {
|
|
26463
26990
|
const s = findChildByLocalName(el, "startPt"), e = findChildByLocalName(el, "endPt");
|
|
26464
|
-
const x1 = x +
|
|
26465
|
-
const x2 = x +
|
|
26991
|
+
const x1 = x + num3(s, "x") * sx, y1 = y + num3(s, "y") * sy;
|
|
26992
|
+
const x2 = x + num3(e, "x") * sx, y2 = y + num3(e, "y") * sy;
|
|
26466
26993
|
emit(ctx, `<line x1="${pt(x1)}" y1="${pt(y1)}" x2="${pt(x2)}" y2="${pt(y2)}" stroke="${escapeXml3(strokeCol)}" stroke-width="${(strokeW || 0.3).toFixed(2)}"${dash}/>`);
|
|
26467
26994
|
} else if (o.tag === "polygon" || o.tag === "curv") {
|
|
26468
26995
|
const pts = [];
|
|
26469
|
-
for (const c of elements2(el)) if (ln2(c) === "pt") pts.push(`${pt(x +
|
|
26996
|
+
for (const c of elements2(el)) if (ln2(c) === "pt") pts.push(`${pt(x + num3(c, "x") * sx)},${pt(y + num3(c, "y") * sy)}`);
|
|
26470
26997
|
if (pts.length >= 2) emit(ctx, `<polygon points="${pts.join(" ")}"${fillAttr}${strokeAttr}/>`);
|
|
26471
26998
|
} else if (o.tag === "arc") {
|
|
26472
26999
|
emit(ctx, `<ellipse cx="${pt(x + w / 2)}" cy="${pt(y + h / 2)}" rx="${pt(w / 2)}" ry="${pt(h / 2)}" fill="none"${strokeAttr || ` stroke="${escapeXml3(strokeCol)}" stroke-width="0.3"`}/>`);
|
|
@@ -26486,13 +27013,17 @@ function cellContentExtent(cell) {
|
|
|
26486
27013
|
for (const s of m.segs) ext = Math.max(ext, s.vertpos + s.textheight);
|
|
26487
27014
|
const baseV = m.segs[0]?.vertpos ?? 0;
|
|
26488
27015
|
for (const o of m.objs) {
|
|
26489
|
-
if (o.inline)
|
|
27016
|
+
if (o.inline) {
|
|
27017
|
+
const h = o.tag === "tbl" ? Math.max(o.height, measureTableHeight(o.el)) : o.height;
|
|
27018
|
+
ext = Math.max(ext, baseV + h);
|
|
27019
|
+
continue;
|
|
27020
|
+
}
|
|
26490
27021
|
const pos = findChildByLocalName(o.el, "pos");
|
|
26491
27022
|
if ((pos?.getAttribute("vertRelTo") ?? "PARA") !== "PARA") continue;
|
|
26492
27023
|
const om = findChildByLocalName(o.el, "outMargin");
|
|
26493
|
-
const pushed = baseV - (
|
|
27024
|
+
const pushed = baseV - (num3(om, "top") + o.height + num3(om, "bottom"));
|
|
26494
27025
|
const anchor = pushed >= -100 ? pushed : baseV;
|
|
26495
|
-
ext = Math.max(ext, anchor +
|
|
27026
|
+
ext = Math.max(ext, anchor + num3(om, "top") + num3(pos, "vertOffset") + o.height);
|
|
26496
27027
|
}
|
|
26497
27028
|
}
|
|
26498
27029
|
return ext;
|
|
@@ -26503,8 +27034,8 @@ function edgeLine(x1, y1, x2, y2, e) {
|
|
|
26503
27034
|
}
|
|
26504
27035
|
function collectCells(tbl) {
|
|
26505
27036
|
const inMargin = findChildByLocalName(tbl, "inMargin");
|
|
26506
|
-
const defL =
|
|
26507
|
-
const defT =
|
|
27037
|
+
const defL = num3(inMargin, "left", 141), defR = num3(inMargin, "right", 141);
|
|
27038
|
+
const defT = num3(inMargin, "top", 141), defB = num3(inMargin, "bottom", 141);
|
|
26508
27039
|
const cells = [];
|
|
26509
27040
|
for (const tr of elements2(tbl)) {
|
|
26510
27041
|
if (ln2(tr) !== "tr") continue;
|
|
@@ -26517,18 +27048,18 @@ function collectCells(tbl) {
|
|
|
26517
27048
|
if (!addr || !csz) continue;
|
|
26518
27049
|
cells.push({
|
|
26519
27050
|
el: tc,
|
|
26520
|
-
ca:
|
|
26521
|
-
ra:
|
|
26522
|
-
cs: Math.max(1,
|
|
26523
|
-
rs: Math.max(1,
|
|
26524
|
-
w:
|
|
26525
|
-
h:
|
|
27051
|
+
ca: num3(addr, "colAddr"),
|
|
27052
|
+
ra: num3(addr, "rowAddr"),
|
|
27053
|
+
cs: Math.max(1, num3(span, "colSpan", 1)),
|
|
27054
|
+
rs: Math.max(1, num3(span, "rowSpan", 1)),
|
|
27055
|
+
w: num3(csz, "width"),
|
|
27056
|
+
h: num3(csz, "height"),
|
|
26526
27057
|
bfId: tc.getAttribute("borderFillIDRef"),
|
|
26527
27058
|
sub: findChildByLocalName(tc, "subList"),
|
|
26528
|
-
marginL: cm ?
|
|
26529
|
-
marginR: cm ?
|
|
26530
|
-
marginT: cm ?
|
|
26531
|
-
marginB: cm ?
|
|
27059
|
+
marginL: cm ? num3(cm, "left", defL) : defL,
|
|
27060
|
+
marginR: cm ? num3(cm, "right", defR) : defR,
|
|
27061
|
+
marginT: cm ? num3(cm, "top", defT) : defT,
|
|
27062
|
+
marginB: cm ? num3(cm, "bottom", defB) : defB
|
|
26532
27063
|
});
|
|
26533
27064
|
}
|
|
26534
27065
|
}
|
|
@@ -26558,7 +27089,7 @@ function drawTable(tbl, tx, ty, ctx, depth) {
|
|
|
26558
27089
|
const nCols = Math.max(...cells.map((c) => c.ca + c.cs));
|
|
26559
27090
|
const nRows = Math.max(...cells.map((c) => c.ra + c.rs));
|
|
26560
27091
|
const colCons = cells.map((c) => ({ a: c.ca, b: c.ca + c.cs, size: c.w }));
|
|
26561
|
-
const colX = solveBoundaries(colCons, nCols,
|
|
27092
|
+
const colX = solveBoundaries(colCons, nCols, num3(tblSz, "width") || void 0);
|
|
26562
27093
|
const rowH = solveRowHeights(
|
|
26563
27094
|
cells.map((c) => ({ rowAddr: c.ra, rowSpan: c.rs, height: c.h, contentH: c.rs === 1 ? cellContentExtent(c) : void 0 })),
|
|
26564
27095
|
nRows
|
|
@@ -26610,7 +27141,7 @@ function imageSymbol(loaded, ctx) {
|
|
|
26610
27141
|
}
|
|
26611
27142
|
function drawPic(pic, x, y, ctx) {
|
|
26612
27143
|
const sz = findChildByLocalName(pic, "sz");
|
|
26613
|
-
const w =
|
|
27144
|
+
const w = num3(sz, "width", 5669), h = num3(sz, "height", 5669);
|
|
26614
27145
|
const img = findFirst(pic, "img");
|
|
26615
27146
|
const ref = img?.getAttribute("binaryItemIDRef");
|
|
26616
27147
|
const loaded = ref != null ? ctx.images.get(ref) : void 0;
|
|
@@ -26623,11 +27154,11 @@ function drawPic(pic, x, y, ctx) {
|
|
|
26623
27154
|
const clip = findChildByLocalName(pic, "imgClip");
|
|
26624
27155
|
const imgDim = findChildByLocalName(pic, "imgDim");
|
|
26625
27156
|
const orgSz = findChildByLocalName(pic, "orgSz");
|
|
26626
|
-
const dimW =
|
|
26627
|
-
const refW = dimW > 0 ? dimW :
|
|
26628
|
-
const refH = dimH > 0 ? dimH :
|
|
26629
|
-
const cl =
|
|
26630
|
-
const cr =
|
|
27157
|
+
const dimW = num3(imgDim, "dimwidth"), dimH = num3(imgDim, "dimheight");
|
|
27158
|
+
const refW = dimW > 0 ? dimW : num3(orgSz, "width");
|
|
27159
|
+
const refH = dimH > 0 ? dimH : num3(orgSz, "height");
|
|
27160
|
+
const cl = num3(clip, "left"), ct = num3(clip, "top");
|
|
27161
|
+
const cr = num3(clip, "right", refW), cb = num3(clip, "bottom", refH);
|
|
26631
27162
|
const cropped = refW > 0 && refH > 0 && clip != null && (cl > 0 || ct > 0 || cr < refW || cb < refH) && cr > cl && cb > ct;
|
|
26632
27163
|
const symId = imageSymbol(loaded, ctx);
|
|
26633
27164
|
if (cropped) {
|
|
@@ -26647,28 +27178,89 @@ function sniffMime(name, bytes) {
|
|
|
26647
27178
|
if (lower.endsWith(".svg")) return "image/svg+xml";
|
|
26648
27179
|
return "image/jpeg";
|
|
26649
27180
|
}
|
|
27181
|
+
function readSectionGeom(root) {
|
|
27182
|
+
const pagePr = findFirst(root, "pagePr");
|
|
27183
|
+
const margin = pagePr ? findChildByLocalName(pagePr, "margin") : null;
|
|
27184
|
+
let PW = num3(pagePr, "width", 59528), PH = num3(pagePr, "height", 84188);
|
|
27185
|
+
if (pagePr?.getAttribute("landscape") === "NARROWLY" && PW < PH) {
|
|
27186
|
+
const t = PW;
|
|
27187
|
+
PW = PH;
|
|
27188
|
+
PH = t;
|
|
27189
|
+
}
|
|
27190
|
+
const ML = num3(margin, "left", 8504);
|
|
27191
|
+
const MT = num3(margin, "top", 5668) + num3(margin, "header", 0);
|
|
27192
|
+
const BODY_H = PH - MT - num3(margin, "bottom", 4252) - num3(margin, "footer", 0);
|
|
27193
|
+
const BODY_W = PW - ML - num3(margin, "right", 8504);
|
|
27194
|
+
return { PW, PH, ML, MT, BODY_W, BODY_H };
|
|
27195
|
+
}
|
|
27196
|
+
function renderSectionToPages(root, geom, ctxBase, hasCache, reflowMode) {
|
|
27197
|
+
const { PW, PH, ML, MT, BODY_W, BODY_H } = geom;
|
|
27198
|
+
if (!hasCache) reflowSection(root, ctxBase.styles, { BODY_W, BODY_H }, reflowMode);
|
|
27199
|
+
const colPr = findFirst(root, "colPr");
|
|
27200
|
+
const multiCol = num3(colPr, "colCount", 1) > 1;
|
|
27201
|
+
const paraSegPages = /* @__PURE__ */ new Map();
|
|
27202
|
+
let nPages = 1;
|
|
27203
|
+
let maxTopV = 0;
|
|
27204
|
+
{
|
|
27205
|
+
let prevV = Number.NEGATIVE_INFINITY;
|
|
27206
|
+
let prevH = Number.NEGATIVE_INFINITY;
|
|
27207
|
+
let cur = 0;
|
|
27208
|
+
for (const p of elements2(root)) {
|
|
27209
|
+
if (ln2(p) !== "p") continue;
|
|
27210
|
+
const lsa = findChildByLocalName(p, "linesegarray");
|
|
27211
|
+
const segEls = lsa ? elements2(lsa).filter((s) => ln2(s) === "lineseg") : [];
|
|
27212
|
+
const pagesOf = [];
|
|
27213
|
+
let paraFirst = true;
|
|
27214
|
+
for (const s of segEls) {
|
|
27215
|
+
const v = num3(s, "vertpos");
|
|
27216
|
+
const h = num3(s, "horzpos");
|
|
27217
|
+
const brk = v < prevV ? !multiCol || h <= prevH : paraFirst && v === prevV && h <= prevH;
|
|
27218
|
+
if (brk) cur++;
|
|
27219
|
+
paraFirst = false;
|
|
27220
|
+
pagesOf.push(cur);
|
|
27221
|
+
maxTopV = Math.max(maxTopV, v + num3(s, "textheight", 1e3));
|
|
27222
|
+
prevV = v;
|
|
27223
|
+
prevH = h;
|
|
27224
|
+
}
|
|
27225
|
+
paraSegPages.set(p, pagesOf);
|
|
27226
|
+
nPages = Math.max(nPages, cur + 1);
|
|
27227
|
+
}
|
|
27228
|
+
}
|
|
27229
|
+
const ctx = {
|
|
27230
|
+
...ctxBase,
|
|
27231
|
+
pages: Array.from({ length: nPages }, () => []),
|
|
27232
|
+
page: 0,
|
|
27233
|
+
geom
|
|
27234
|
+
};
|
|
27235
|
+
for (const p of elements2(root)) {
|
|
27236
|
+
if (ln2(p) !== "p") continue;
|
|
27237
|
+
drawPara(p, ML, MT, BODY_W, ctx, 0, paraSegPages.get(p));
|
|
27238
|
+
}
|
|
27239
|
+
const pageH = nPages === 1 ? Math.max(PH, MT + maxTopV + 2e3) : PH;
|
|
27240
|
+
return { pages: ctx.pages, pageH };
|
|
27241
|
+
}
|
|
26650
27242
|
async function renderHwpxToSvg(input, options) {
|
|
26651
27243
|
const maxImg = options?.maxImageBytes ?? 40 * 1024 * 1024;
|
|
26652
27244
|
const ab = input instanceof Uint8Array ? input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength) : input;
|
|
26653
27245
|
precheckZipSize(ab, MAX_DECOMPRESS_SIZE, MAX_ZIP_ENTRIES);
|
|
26654
27246
|
let zip;
|
|
26655
27247
|
try {
|
|
26656
|
-
zip = await
|
|
27248
|
+
zip = await JSZip13.loadAsync(input);
|
|
26657
27249
|
} catch {
|
|
26658
27250
|
throw new KordocError("HWPX(ZIP) \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uB80C\uB354\uB294 HWPX\uB9CC \uC9C0\uC6D0");
|
|
26659
27251
|
}
|
|
26660
|
-
const
|
|
26661
|
-
if (
|
|
26662
|
-
const secXml = await secFile.async("string");
|
|
26663
|
-
if (secXml.length > MAX_DECOMPRESS_SIZE) throw new KordocError("\uC139\uC158 XML\uC774 \uD5C8\uC6A9 \uD06C\uAE30\uB97C \uCD08\uACFC");
|
|
26664
|
-
const hasCache = /<(?:[A-Za-z][\w.-]*:)?linesegarray[\s/>]/.test(secXml);
|
|
26665
|
-
if (!hasCache && !options?.reflow) {
|
|
26666
|
-
throw new KordocError("\uC870\uD310 \uCE90\uC2DC(linesegarray) \uC5C6\uC74C \u2014 \uD55C\uCEF4\uC5D0\uC11C \uC800\uC7A5\uD55C HWPX\uB9CC \uB80C\uB354 \uAC00\uB2A5 (reflow \uC635\uC158\uC73C\uB85C \uD569\uC131 \uB80C\uB354 \uAC00\uB2A5)");
|
|
26667
|
-
}
|
|
27252
|
+
const secFiles = zip.file(/Contents\/section\d+\.xml$/i).sort((a, b) => a.name.localeCompare(b.name));
|
|
27253
|
+
if (secFiles.length === 0) throw new KordocError("Contents/section0.xml \uC5C6\uC74C \u2014 HWPX\uAC00 \uC544\uB2C8\uAC70\uB098 \uC190\uC0C1\uB428");
|
|
26668
27254
|
const warnings = [];
|
|
26669
27255
|
const headFile = zip.file("Contents/header.xml") ?? zip.file("Contents/head.xml");
|
|
26670
27256
|
const styles = headFile ? parseRenderStyles(await headFile.async("string")) : { charPr: /* @__PURE__ */ new Map(), paraAlign: /* @__PURE__ */ new Map(), paraGeom: /* @__PURE__ */ new Map(), borderFill: /* @__PURE__ */ new Map() };
|
|
26671
27257
|
if (!headFile) warnings.push("header.xml \uC5C6\uC74C \u2014 \uAE30\uBCF8 \uC2A4\uD0C0\uC77C\uB85C \uB80C\uB354");
|
|
27258
|
+
const secXmls = [];
|
|
27259
|
+
for (const f of secFiles) {
|
|
27260
|
+
const xml = await f.async("string");
|
|
27261
|
+
if (xml.length > MAX_DECOMPRESS_SIZE) throw new KordocError("\uC139\uC158 XML\uC774 \uD5C8\uC6A9 \uD06C\uAE30\uB97C \uCD08\uACFC");
|
|
27262
|
+
secXmls.push(xml);
|
|
27263
|
+
}
|
|
26672
27264
|
const binmap = /* @__PURE__ */ new Map();
|
|
26673
27265
|
const hpf = zip.file(/content\.hpf$/i)[0];
|
|
26674
27266
|
if (hpf) {
|
|
@@ -26680,7 +27272,7 @@ async function renderHwpxToSvg(input, options) {
|
|
|
26680
27272
|
const MAX_TOTAL_IMAGE_BYTES = 128 * 1024 * 1024;
|
|
26681
27273
|
const images = /* @__PURE__ */ new Map();
|
|
26682
27274
|
const refs = /* @__PURE__ */ new Set();
|
|
26683
|
-
for (const m of
|
|
27275
|
+
for (const xml of secXmls) for (const m of xml.matchAll(/binaryItemIDRef="([^"]+)"/g)) refs.add(m[1]);
|
|
26684
27276
|
let totalImgBytes = 0;
|
|
26685
27277
|
for (const ref of refs) {
|
|
26686
27278
|
if (images.size >= MAX_IMAGE_REFS) {
|
|
@@ -26707,48 +27299,7 @@ async function renderHwpxToSvg(input, options) {
|
|
|
26707
27299
|
totalImgBytes += bytes.length;
|
|
26708
27300
|
images.set(ref, { dataUri: `data:${sniffMime(href, bytes)};base64,${Buffer.from(bytes).toString("base64")}` });
|
|
26709
27301
|
}
|
|
26710
|
-
const
|
|
26711
|
-
const root = doc.documentElement;
|
|
26712
|
-
if (!root) throw new KordocError("\uC139\uC158 XML \uD30C\uC2F1 \uC2E4\uD328");
|
|
26713
|
-
const pagePr = findFirst(root, "pagePr");
|
|
26714
|
-
const margin = pagePr ? findChildByLocalName(pagePr, "margin") : null;
|
|
26715
|
-
const PW = num2(pagePr, "width", 59528), PH = num2(pagePr, "height", 84188);
|
|
26716
|
-
const ML = num2(margin, "left", 8504);
|
|
26717
|
-
const MT = num2(margin, "top", 5668) + num2(margin, "header", 0);
|
|
26718
|
-
const BODY_H = PH - MT - num2(margin, "bottom", 4252) - num2(margin, "footer", 0);
|
|
26719
|
-
const BODY_W = PW - ML - num2(margin, "right", 8504);
|
|
26720
|
-
if (!hasCache) reflowSection(root, styles, { BODY_W, BODY_H }, options?.reflowMode ?? "keep");
|
|
26721
|
-
const colPr = findFirst(root, "colPr");
|
|
26722
|
-
const multiCol = num2(colPr, "colCount", 1) > 1;
|
|
26723
|
-
const paraSegPages = /* @__PURE__ */ new Map();
|
|
26724
|
-
let nPages = 1;
|
|
26725
|
-
let maxTopV = 0;
|
|
26726
|
-
{
|
|
26727
|
-
let prevV = Number.NEGATIVE_INFINITY;
|
|
26728
|
-
let prevH = Number.NEGATIVE_INFINITY;
|
|
26729
|
-
let cur = 0;
|
|
26730
|
-
for (const p of elements2(root)) {
|
|
26731
|
-
if (ln2(p) !== "p") continue;
|
|
26732
|
-
const lsa = findChildByLocalName(p, "linesegarray");
|
|
26733
|
-
const segEls = lsa ? elements2(lsa).filter((s) => ln2(s) === "lineseg") : [];
|
|
26734
|
-
const pagesOf = [];
|
|
26735
|
-
for (const s of segEls) {
|
|
26736
|
-
const v = num2(s, "vertpos");
|
|
26737
|
-
const h = num2(s, "horzpos");
|
|
26738
|
-
if (v < prevV && (!multiCol || h <= prevH)) cur++;
|
|
26739
|
-
pagesOf.push(cur);
|
|
26740
|
-
maxTopV = Math.max(maxTopV, v + num2(s, "textheight", 1e3));
|
|
26741
|
-
prevV = v;
|
|
26742
|
-
prevH = h;
|
|
26743
|
-
}
|
|
26744
|
-
paraSegPages.set(p, pagesOf);
|
|
26745
|
-
nPages = Math.max(nPages, cur + 1);
|
|
26746
|
-
}
|
|
26747
|
-
}
|
|
26748
|
-
const ctx = {
|
|
26749
|
-
pages: Array.from({ length: nPages }, () => []),
|
|
26750
|
-
page: 0,
|
|
26751
|
-
geom: { PW, PH, ML, MT, BODY_W, BODY_H },
|
|
27302
|
+
const ctxBase = {
|
|
26752
27303
|
styles,
|
|
26753
27304
|
images,
|
|
26754
27305
|
defs: [],
|
|
@@ -26757,23 +27308,57 @@ async function renderHwpxToSvg(input, options) {
|
|
|
26757
27308
|
warned: /* @__PURE__ */ new Set(),
|
|
26758
27309
|
stats: { texts: 0, images: 0, tables: 0 }
|
|
26759
27310
|
};
|
|
26760
|
-
|
|
26761
|
-
|
|
26762
|
-
|
|
27311
|
+
const rendered = [];
|
|
27312
|
+
let noCacheSkipped = false;
|
|
27313
|
+
for (let si = 0; si < secXmls.length; si++) {
|
|
27314
|
+
const secXml = secXmls[si];
|
|
27315
|
+
const hasCache = /<(?:[A-Za-z][\w.-]*:)?linesegarray[\s/>]/.test(secXml);
|
|
27316
|
+
if (!hasCache && !options?.reflow) {
|
|
27317
|
+
noCacheSkipped = true;
|
|
27318
|
+
warnings.push(`\uAD6C\uC5ED ${si}: \uC870\uD310 \uCE90\uC2DC \uC5C6\uC74C \u2014 reflow \uC635\uC158 \uD544\uC694, \uC0DD\uB7B5`);
|
|
27319
|
+
continue;
|
|
27320
|
+
}
|
|
27321
|
+
const doc = createXmlParser().parseFromString(secXml, "text/xml");
|
|
27322
|
+
const root = doc.documentElement;
|
|
27323
|
+
if (!root) {
|
|
27324
|
+
warnings.push(`\uAD6C\uC5ED ${si} XML \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uC0DD\uB7B5`);
|
|
27325
|
+
continue;
|
|
27326
|
+
}
|
|
27327
|
+
const geom = readSectionGeom(root);
|
|
27328
|
+
const { pages, pageH } = renderSectionToPages(root, geom, ctxBase, hasCache, options?.reflowMode ?? "keep");
|
|
27329
|
+
rendered.push({ pages, PW: geom.PW, pageH, clipId: `pgclip${si}` });
|
|
27330
|
+
}
|
|
27331
|
+
if (rendered.length === 0) {
|
|
27332
|
+
if (noCacheSkipped) {
|
|
27333
|
+
throw new KordocError("\uC870\uD310 \uCE90\uC2DC(linesegarray) \uC5C6\uC74C \u2014 \uD55C\uCEF4\uC5D0\uC11C \uC800\uC7A5\uD55C HWPX\uB9CC \uB80C\uB354 \uAC00\uB2A5 (reflow \uC635\uC158\uC73C\uB85C \uD569\uC131 \uB80C\uB354 \uAC00\uB2A5)");
|
|
27334
|
+
}
|
|
27335
|
+
throw new KordocError("\uB80C\uB354\uD560 \uAD6C\uC5ED\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 HWPX\uAC00 \uC190\uC0C1\uB418\uC5C8\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
|
|
26763
27336
|
}
|
|
26764
|
-
const pageH = nPages === 1 ? Math.max(PH, MT + maxTopV + 2e3) : PH;
|
|
26765
27337
|
const GAP = 2400;
|
|
26766
|
-
const
|
|
26767
|
-
const
|
|
26768
|
-
|
|
27338
|
+
const clipDefs = [];
|
|
27339
|
+
const groups = [];
|
|
27340
|
+
let y = 0;
|
|
27341
|
+
let maxPW = 0;
|
|
27342
|
+
let pageNo = 0;
|
|
27343
|
+
for (const rs of rendered) {
|
|
27344
|
+
maxPW = Math.max(maxPW, rs.PW);
|
|
27345
|
+
clipDefs.push(`<clipPath id="${rs.clipId}"><rect x="0" y="0" width="${pt(rs.PW)}" height="${pt(rs.pageH)}"/></clipPath>`);
|
|
27346
|
+
for (const buf of rs.pages) {
|
|
27347
|
+
pageNo++;
|
|
27348
|
+
groups.push(
|
|
27349
|
+
`<g data-page="${pageNo}" transform="translate(0 ${pt(y)})"><rect width="${pt(rs.PW)}" height="${pt(rs.pageH)}" fill="white" stroke="#c9c7c4" stroke-width="0.75"/><g clip-path="url(#${rs.clipId})">
|
|
26769
27350
|
${buf.join("\n")}
|
|
26770
27351
|
</g></g>`
|
|
26771
|
-
|
|
26772
|
-
|
|
26773
|
-
|
|
26774
|
-
|
|
27352
|
+
);
|
|
27353
|
+
y += rs.pageH + GAP;
|
|
27354
|
+
}
|
|
27355
|
+
}
|
|
27356
|
+
const totalH = Math.max(0, y - GAP);
|
|
27357
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${pt(maxPW)} ${pt(totalH)}" width="${pt(maxPW)}pt" height="${pt(totalH)}pt" font-family="'HCR Batang','\uD568\uCD08\uB86C\uBC14\uD0D5','Hancom Batang',AppleMyungjo,'Noto Serif CJK KR',serif" xml:space="preserve">
|
|
27358
|
+
<defs>${clipDefs.join("")}${ctxBase.defs.join("")}</defs>
|
|
27359
|
+
${groups.join("\n")}
|
|
26775
27360
|
</svg>`;
|
|
26776
|
-
return { svg, width: Math.round(
|
|
27361
|
+
return { svg, width: Math.round(maxPW) / 100, height: Math.round(totalH) / 100, pageCount: pageNo, warnings, stats: ctxBase.stats };
|
|
26777
27362
|
}
|
|
26778
27363
|
|
|
26779
27364
|
// src/index.ts
|
|
@@ -26863,7 +27448,7 @@ async function parseHwp(buffer, options) {
|
|
|
26863
27448
|
async function parsePdf(buffer, options) {
|
|
26864
27449
|
let parsePdfDocument;
|
|
26865
27450
|
try {
|
|
26866
|
-
const mod = await import("./parser-
|
|
27451
|
+
const mod = await import("./parser-5D6BQYTX.js");
|
|
26867
27452
|
parsePdfDocument = mod.parsePdfDocument;
|
|
26868
27453
|
} catch {
|
|
26869
27454
|
return {
|
|
@@ -26978,6 +27563,7 @@ export {
|
|
|
26978
27563
|
fillWithUniqueGuard,
|
|
26979
27564
|
fitRatioForFewerLines,
|
|
26980
27565
|
formatFillValue,
|
|
27566
|
+
hwpxToProfile,
|
|
26981
27567
|
inferFieldType,
|
|
26982
27568
|
isHwpxFile,
|
|
26983
27569
|
isLabelCell,
|