hwpkit-dev 0.0.3 → 0.0.5
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/ .npmignore +1 -0
- package/README.md +8 -8
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +573 -230
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +573 -230
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/decoders/hwp/HwpScanner.ts +174 -57
- package/src/decoders/hwpx/HwpxDecoder.ts +23 -12
- package/src/encoders/docx/DocxEncoder.ts +49 -4
- package/src/encoders/hwp/HwpEncoder.ts +309 -163
- package/src/encoders/hwpx/HwpxEncoder.ts +249 -103
- package/src/model/doc-props.ts +5 -5
- package/src/model/doc-tree.ts +2 -2
- package/test-styling.ts +0 -210
package/dist/index.mjs
CHANGED
|
@@ -1353,6 +1353,17 @@ function decodeGrid(tbl, ctx) {
|
|
|
1353
1353
|
const headerRow = tblAttr.repeatHeader === "1";
|
|
1354
1354
|
const gridProps = { headerRow: headerRow || void 0 };
|
|
1355
1355
|
if (borderFill?.stroke) gridProps.defaultStroke = borderFill.stroke;
|
|
1356
|
+
const posAttr = tbl?.["hp:pos"]?.[0]?._attr ?? {};
|
|
1357
|
+
if (posAttr.horzAlign) {
|
|
1358
|
+
const alignMap = {
|
|
1359
|
+
LEFT: "left",
|
|
1360
|
+
RIGHT: "right",
|
|
1361
|
+
CENTER: "center",
|
|
1362
|
+
JUSTIFY: "justify"
|
|
1363
|
+
};
|
|
1364
|
+
const a = alignMap[posAttr.horzAlign];
|
|
1365
|
+
if (a) gridProps.align = a;
|
|
1366
|
+
}
|
|
1356
1367
|
const rowArr = getTag(tbl, "hp:tr", "hp:ROW");
|
|
1357
1368
|
for (const row of rowArr) {
|
|
1358
1369
|
const cells = getTag(row, "hp:tc", "hp:CELL");
|
|
@@ -1435,16 +1446,15 @@ function decodeGrid(tbl, ctx) {
|
|
|
1435
1446
|
};
|
|
1436
1447
|
cellProps.va = vaMap[subAttr.vertAlign];
|
|
1437
1448
|
}
|
|
1438
|
-
const
|
|
1439
|
-
const
|
|
1440
|
-
const
|
|
1441
|
-
const
|
|
1442
|
-
const
|
|
1443
|
-
|
|
1444
|
-
if (
|
|
1445
|
-
if (
|
|
1446
|
-
if (
|
|
1447
|
-
if (mB !== HWPX_DEFAULT_MARGIN_TB) cellProps.padB = Metric.hwpToPt(mB);
|
|
1449
|
+
const cellMarginAttr = cell?.["hp:cellMargin"]?.[0]?._attr ?? {};
|
|
1450
|
+
const mL = cellMarginAttr.left !== void 0 ? Number(cellMarginAttr.left) : -1;
|
|
1451
|
+
const mR = cellMarginAttr.right !== void 0 ? Number(cellMarginAttr.right) : -1;
|
|
1452
|
+
const mT = cellMarginAttr.top !== void 0 ? Number(cellMarginAttr.top) : -1;
|
|
1453
|
+
const mB = cellMarginAttr.bottom !== void 0 ? Number(cellMarginAttr.bottom) : -1;
|
|
1454
|
+
if (mL >= 0) cellProps.padL = Metric.hwpToPt(mL);
|
|
1455
|
+
if (mR >= 0) cellProps.padR = Metric.hwpToPt(mR);
|
|
1456
|
+
if (mT >= 0) cellProps.padT = Metric.hwpToPt(mT);
|
|
1457
|
+
if (mB >= 0) cellProps.padB = Metric.hwpToPt(mB);
|
|
1448
1458
|
const cellSpan = cell?.["hp:cellSpan"]?.[0]?._attr ?? {};
|
|
1449
1459
|
const cs = Number(cellSpan.colSpan ?? ca.ColSpan ?? 1);
|
|
1450
1460
|
const rs = Number(cellSpan.rowSpan ?? ca.RowSpan ?? 1);
|
|
@@ -1704,6 +1714,9 @@ var CTRL_IMAGE = 1768777504;
|
|
|
1704
1714
|
var CTRL_OBJ = 1868720672;
|
|
1705
1715
|
var CTRL_FIG = 1718183712;
|
|
1706
1716
|
var CTRL_GSO = 1735618336;
|
|
1717
|
+
var CTRL_HEAD = 1751474532;
|
|
1718
|
+
var CTRL_FOOT = 1718579060;
|
|
1719
|
+
var CTRL_ATNO = 1635020399;
|
|
1707
1720
|
function parseRecords(data) {
|
|
1708
1721
|
const out = [];
|
|
1709
1722
|
let off = 0;
|
|
@@ -1781,19 +1794,29 @@ function parseCharShape(d) {
|
|
|
1781
1794
|
textColor: d.length >= 56 ? colorRef(d, 52) : "000000"
|
|
1782
1795
|
};
|
|
1783
1796
|
}
|
|
1784
|
-
var ALIGN_TBL = { 0: "justify", 1: "left", 2: "right", 3: "center", 4: "
|
|
1797
|
+
var ALIGN_TBL = { 0: "justify", 1: "left", 2: "right", 3: "center", 4: "distribute", 5: "distribute_space" };
|
|
1785
1798
|
function parseParaShape(d) {
|
|
1786
|
-
if (d.length < 4) return { align: "left", spaceBefore: 0, spaceAfter: 0, lineSpacing: 160, leftMargin: 0, indent: 0 };
|
|
1799
|
+
if (d.length < 4) return { align: "left", spaceBefore: 0, spaceAfter: 0, lineSpacing: 160, lineSpacingType: 0, leftMargin: 0, rightMargin: 0, indent: 0 };
|
|
1787
1800
|
const attr = BinaryKit.readU32LE(d, 0);
|
|
1801
|
+
const lineSpacingType = attr & 3;
|
|
1802
|
+
const align = ALIGN_TBL[attr >> 2 & 7] ?? "left";
|
|
1803
|
+
const vVal = attr >> 18 & 3;
|
|
1804
|
+
const verAlign = vVal === 1 ? "top" : vVal === 2 ? "center" : vVal === 3 ? "bottom" : "baseline";
|
|
1805
|
+
const lineWrap = "break";
|
|
1788
1806
|
return {
|
|
1789
|
-
align
|
|
1807
|
+
align,
|
|
1808
|
+
lineSpacingType,
|
|
1790
1809
|
leftMargin: d.length >= 8 ? i32(d, 4) : 0,
|
|
1791
|
-
// offset 4:
|
|
1810
|
+
// offset 4: 문단 몸체 왼쪽 여백 (HWPUNIT)
|
|
1811
|
+
rightMargin: d.length >= 12 ? i32(d, 8) : 0,
|
|
1812
|
+
// offset 8: 문단 몸체 오른쪽 여백 (HWPUNIT)
|
|
1792
1813
|
indent: d.length >= 16 ? i32(d, 12) : 0,
|
|
1793
|
-
// offset 12:
|
|
1814
|
+
// offset 12: 첫 줄 들여쓰기 (HWPUNIT)
|
|
1794
1815
|
spaceBefore: d.length >= 20 ? i32(d, 16) : 0,
|
|
1795
1816
|
spaceAfter: d.length >= 24 ? i32(d, 20) : 0,
|
|
1796
|
-
lineSpacing: d.length >= 28 ? i32(d, 24) : 160
|
|
1817
|
+
lineSpacing: d.length >= 28 ? i32(d, 24) : 160,
|
|
1818
|
+
verAlign,
|
|
1819
|
+
lineWrap
|
|
1797
1820
|
};
|
|
1798
1821
|
}
|
|
1799
1822
|
var BORDER_W_PT = [0.28, 0.34, 0.43, 0.57, 0.71, 0.85, 1.13, 1.42, 1.7, 1.98, 2.84, 4.25, 5.67, 8.5, 11.34, 14.17];
|
|
@@ -1849,6 +1872,8 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1849
1872
|
const hdr = recs[start];
|
|
1850
1873
|
const lv = hdr.level;
|
|
1851
1874
|
const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;
|
|
1875
|
+
const hwpStyleId = hdr.data.length >= 11 ? hdr.data[10] : 0;
|
|
1876
|
+
const divideSort = hdr.data.length >= 12 ? hdr.data[11] : 0;
|
|
1852
1877
|
const ps = di.paraShapes[psId];
|
|
1853
1878
|
let text = null;
|
|
1854
1879
|
let csPairs = [];
|
|
@@ -1866,23 +1891,48 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1866
1891
|
} else if (r.tag === TAG_CTRL_HEADER && r.level === lv + 1) {
|
|
1867
1892
|
if (r.data.length >= 4) {
|
|
1868
1893
|
const ctrlId = BinaryKit.readU32LE(r.data, 0);
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1894
|
+
if (ctrlId === CTRL_HEAD || ctrlId === CTRL_FOOT) {
|
|
1895
|
+
const ctrlLv = r.level;
|
|
1896
|
+
const hfParas = [];
|
|
1897
|
+
let j = i + 1;
|
|
1898
|
+
while (j < recs.length && recs[j].level > ctrlLv) {
|
|
1899
|
+
if (recs[j].tag === TAG_PARA_HEADER) {
|
|
1900
|
+
const pr = shield.guard(
|
|
1901
|
+
() => parseParagraphGroup(recs, j, di, shield, gsoCtx),
|
|
1902
|
+
{ nodes: [], next: j + 1 },
|
|
1903
|
+
`hwp:hf@${j}`
|
|
1904
|
+
);
|
|
1905
|
+
hfParas.push(...pr.nodes.filter((n) => n.tag === "para"));
|
|
1906
|
+
j = pr.next;
|
|
1907
|
+
} else {
|
|
1908
|
+
j++;
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
if (hfParas.length > 0) {
|
|
1912
|
+
const key = ctrlId === CTRL_HEAD ? "headers" : "footers";
|
|
1913
|
+
if (!gsoCtx[key]) gsoCtx[key] = hfParas;
|
|
1914
|
+
}
|
|
1915
|
+
i = j;
|
|
1884
1916
|
} else {
|
|
1885
|
-
|
|
1917
|
+
const MAX_HWP = 1e6;
|
|
1918
|
+
const rawW = r.data.length >= 24 ? BinaryKit.readU32LE(r.data, 16) : 0;
|
|
1919
|
+
const rawH = r.data.length >= 28 ? BinaryKit.readU32LE(r.data, 20) : 0;
|
|
1920
|
+
const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;
|
|
1921
|
+
const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;
|
|
1922
|
+
const atnoType = ctrlId === CTRL_ATNO && r.data.length >= 8 ? BinaryKit.readU32LE(r.data, 4) & 15 : void 0;
|
|
1923
|
+
const imgId = ctrlId === CTRL_GSO ? gsoCtx.count++ : r.data.length >= 6 ? BinaryKit.readU16LE(r.data, 4) : 0;
|
|
1924
|
+
ctrlHeaders.push({ ctrlId, imgId, wPt, hPt, atnoType });
|
|
1925
|
+
if (ctrlId === CTRL_TABLE) {
|
|
1926
|
+
const tr = shield.guard(
|
|
1927
|
+
() => parseTableCtrl(recs, i, di, shield, gsoCtx),
|
|
1928
|
+
{ grid: null, next: skipKids(recs, i) },
|
|
1929
|
+
`hwp:tbl@${i}`
|
|
1930
|
+
);
|
|
1931
|
+
if (tr.grid) grids.push(tr.grid);
|
|
1932
|
+
i = tr.next;
|
|
1933
|
+
} else {
|
|
1934
|
+
i = skipKids(recs, i);
|
|
1935
|
+
}
|
|
1886
1936
|
}
|
|
1887
1937
|
} else {
|
|
1888
1938
|
i = skipKids(recs, i);
|
|
@@ -1892,13 +1942,35 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1892
1942
|
}
|
|
1893
1943
|
}
|
|
1894
1944
|
const nodes = [];
|
|
1895
|
-
|
|
1945
|
+
{
|
|
1896
1946
|
const paraContent = [];
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1947
|
+
const atnoCtrls = [];
|
|
1948
|
+
if (text && text.controls.length > 0) {
|
|
1949
|
+
for (let ci = 0; ci < text.controls.length; ci++) {
|
|
1950
|
+
const ch = ctrlHeaders[ci];
|
|
1951
|
+
if (ch && ch.ctrlId === CTRL_ATNO)
|
|
1952
|
+
atnoCtrls.push({ pos: text.controls[ci].pos, type: ch.atnoType ?? 0 });
|
|
1953
|
+
}
|
|
1954
|
+
atnoCtrls.sort((a, b) => a.pos - b.pos);
|
|
1955
|
+
}
|
|
1956
|
+
if (text && text.chars.length > 0) {
|
|
1957
|
+
if (atnoCtrls.length > 0) {
|
|
1958
|
+
let k = 0;
|
|
1959
|
+
for (const ac of atnoCtrls) {
|
|
1960
|
+
const seg = [];
|
|
1961
|
+
while (k < text.chars.length && text.chars[k].pos < ac.pos) seg.push(text.chars[k++]);
|
|
1962
|
+
if (seg.length > 0) paraContent.push(...resolveCharShapes(seg, csPairs, di));
|
|
1963
|
+
paraContent.push(buildPageNum(ac.type === 0 ? "decimal" : "total"));
|
|
1964
|
+
}
|
|
1965
|
+
const rest = text.chars.slice(k);
|
|
1966
|
+
if (rest.length > 0) paraContent.push(...resolveCharShapes(rest, csPairs, di));
|
|
1967
|
+
} else {
|
|
1968
|
+
paraContent.push(...resolveCharShapes(text.chars, csPairs, di));
|
|
1969
|
+
}
|
|
1970
|
+
} else if (atnoCtrls.length > 0) {
|
|
1971
|
+
for (const ac of atnoCtrls) paraContent.push(buildPageNum(ac.type === 0 ? "decimal" : "total"));
|
|
1900
1972
|
}
|
|
1901
|
-
if (text.controls.length > 0) {
|
|
1973
|
+
if (text && text.controls.length > 0) {
|
|
1902
1974
|
for (let ci = 0; ci < text.controls.length; ci++) {
|
|
1903
1975
|
const ch = ctrlHeaders[ci];
|
|
1904
1976
|
if (!ch) continue;
|
|
@@ -1908,11 +1980,15 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1908
1980
|
paraContent.push(buildSpan(`__EXT_${ch.imgId}${dimStr}__`));
|
|
1909
1981
|
}
|
|
1910
1982
|
}
|
|
1911
|
-
if (
|
|
1912
|
-
nodes.push(buildPara(
|
|
1983
|
+
if (divideSort & 4) {
|
|
1984
|
+
nodes.push(buildPara([{ tag: "span", props: {}, kids: [buildPb()] }]));
|
|
1913
1985
|
}
|
|
1986
|
+
nodes.push(...grids);
|
|
1987
|
+
nodes.push(buildPara(
|
|
1988
|
+
paraContent.length > 0 ? paraContent : [buildSpan("")],
|
|
1989
|
+
buildParaProps(ps, hwpStyleId)
|
|
1990
|
+
));
|
|
1914
1991
|
}
|
|
1915
|
-
nodes.push(...grids);
|
|
1916
1992
|
return { nodes, next: i };
|
|
1917
1993
|
}
|
|
1918
1994
|
function skipKids(recs, idx) {
|
|
@@ -1921,7 +1997,7 @@ function skipKids(recs, idx) {
|
|
|
1921
1997
|
while (i < recs.length && recs[i].level > lv) i++;
|
|
1922
1998
|
return i;
|
|
1923
1999
|
}
|
|
1924
|
-
var EXT_CTRL = /* @__PURE__ */ new Set([2, 3, 11, 12, 14, 15]);
|
|
2000
|
+
var EXT_CTRL = /* @__PURE__ */ new Set([2, 3, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]);
|
|
1925
2001
|
var INL_CTRL = /* @__PURE__ */ new Set([4, 5, 6, 7, 8]);
|
|
1926
2002
|
function decodeParaText(d) {
|
|
1927
2003
|
const chars = [];
|
|
@@ -2219,6 +2295,8 @@ function parseCellRec(d, tag, recs, cStart, cEnd, di, shield, seqIdx, colCnt, gs
|
|
|
2219
2295
|
const hdr = recs[k];
|
|
2220
2296
|
const lv = hdr.level;
|
|
2221
2297
|
const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;
|
|
2298
|
+
const cellStyleId = hdr.data.length >= 11 ? hdr.data[10] : 0;
|
|
2299
|
+
const cellDivide = hdr.data.length >= 12 ? hdr.data[11] : 0;
|
|
2222
2300
|
const ps = di.paraShapes[psId];
|
|
2223
2301
|
let txt = null;
|
|
2224
2302
|
let csp = [];
|
|
@@ -2270,7 +2348,8 @@ function parseCellRec(d, tag, recs, cStart, cEnd, di, shield, seqIdx, colCnt, gs
|
|
|
2270
2348
|
}
|
|
2271
2349
|
}
|
|
2272
2350
|
const kids = paraContent.length > 0 ? paraContent : [buildSpan("")];
|
|
2273
|
-
const items = [buildPara(kids, buildParaProps(ps))
|
|
2351
|
+
const items = [...innerGrids, buildPara(kids, buildParaProps(ps, cellStyleId))];
|
|
2352
|
+
if (cellDivide & 4) items.unshift(buildPara([{ tag: "span", props: {}, kids: [buildPb()] }]));
|
|
2274
2353
|
return { items, next: j };
|
|
2275
2354
|
},
|
|
2276
2355
|
{ items: [buildPara([buildSpan("")])], next: k + 1 },
|
|
@@ -2323,6 +2402,8 @@ function parsePageDef(d) {
|
|
|
2323
2402
|
const mr = BinaryKit.readU32LE(d, 12);
|
|
2324
2403
|
const mt = BinaryKit.readU32LE(d, 16);
|
|
2325
2404
|
const mb = BinaryKit.readU32LE(d, 20);
|
|
2405
|
+
const header = d.length >= 28 ? BinaryKit.readU32LE(d, 24) : 0;
|
|
2406
|
+
const footer = d.length >= 32 ? BinaryKit.readU32LE(d, 28) : 0;
|
|
2326
2407
|
const at = d.length >= 40 ? BinaryKit.readU32LE(d, 36) : 0;
|
|
2327
2408
|
return {
|
|
2328
2409
|
wPt: Metric.hwpToPt(w),
|
|
@@ -2331,6 +2412,8 @@ function parsePageDef(d) {
|
|
|
2331
2412
|
mr: Metric.hwpToPt(mr),
|
|
2332
2413
|
mt: Metric.hwpToPt(mt),
|
|
2333
2414
|
mb: Metric.hwpToPt(mb),
|
|
2415
|
+
headerPt: header > 0 ? Metric.hwpToPt(header) : void 0,
|
|
2416
|
+
footerPt: footer > 0 ? Metric.hwpToPt(footer) : void 0,
|
|
2334
2417
|
orient: at & 1 ? "landscape" : "portrait"
|
|
2335
2418
|
};
|
|
2336
2419
|
}
|
|
@@ -2361,16 +2444,24 @@ function strokeFromBF(bfId, di) {
|
|
|
2361
2444
|
const b = bf.borders[0];
|
|
2362
2445
|
return { kind: BORDER_KIND[b.type] ?? "solid", pt: b.widthPt, color: b.color };
|
|
2363
2446
|
}
|
|
2364
|
-
function buildParaProps(ps) {
|
|
2365
|
-
|
|
2366
|
-
|
|
2447
|
+
function buildParaProps(ps, hwpStyleId) {
|
|
2448
|
+
const p = hwpStyleId !== void 0 ? { hwpStyleId } : {};
|
|
2449
|
+
if (!ps) return p;
|
|
2367
2450
|
if (ps.align && ps.align !== "left") p.align = ps.align;
|
|
2368
2451
|
if (ps.spaceBefore > 0) p.spaceBefore = Metric.hwpToPt(ps.spaceBefore);
|
|
2369
2452
|
if (ps.spaceAfter > 0) p.spaceAfter = Metric.hwpToPt(ps.spaceAfter);
|
|
2370
|
-
if (ps.
|
|
2453
|
+
if (ps.lineSpacingType === 1) {
|
|
2454
|
+
if (ps.lineSpacing > 0) p.lineHeightFixed = Metric.hwpToPt(ps.lineSpacing);
|
|
2455
|
+
} else {
|
|
2456
|
+
if (ps.lineSpacing > 0) p.lineHeight = ps.lineSpacing / 100;
|
|
2457
|
+
}
|
|
2371
2458
|
const leftMarginPt = Math.max(0, Metric.hwpToPt(ps.leftMargin));
|
|
2372
2459
|
if (leftMarginPt > 0) p.leftMargin = leftMarginPt;
|
|
2460
|
+
const rightMarginPt = Math.max(0, Metric.hwpToPt(ps.rightMargin));
|
|
2461
|
+
if (rightMarginPt > 0) p.indentRightPt = rightMarginPt;
|
|
2373
2462
|
if (ps.indent !== 0) p.firstLineIndentPt = Metric.hwpToPt(ps.indent);
|
|
2463
|
+
if (ps.verAlign && ps.verAlign !== "baseline") p.verAlign = ps.verAlign;
|
|
2464
|
+
if (ps.lineWrap && ps.lineWrap !== "break") p.lineWrap = ps.lineWrap;
|
|
2374
2465
|
return p;
|
|
2375
2466
|
}
|
|
2376
2467
|
var HwpScanner = class {
|
|
@@ -2438,7 +2529,10 @@ var HwpScanner = class {
|
|
|
2438
2529
|
}
|
|
2439
2530
|
warns.push(...shield.flush());
|
|
2440
2531
|
const content = allContent.length > 0 ? allContent : [buildPara([buildSpan("")])];
|
|
2441
|
-
return succeed(buildRoot({}, [buildSheet(content, pageDims
|
|
2532
|
+
return succeed(buildRoot({}, [buildSheet(content, pageDims, {
|
|
2533
|
+
headers: gsoCtx.headers ? { default: gsoCtx.headers } : void 0,
|
|
2534
|
+
footers: gsoCtx.footers ? { default: gsoCtx.footers } : void 0
|
|
2535
|
+
})]), warns);
|
|
2442
2536
|
} catch (e) {
|
|
2443
2537
|
warns.push(...shield.flush());
|
|
2444
2538
|
return fail(`HWP decode error: ${e?.message ?? String(e)}`, warns);
|
|
@@ -4409,6 +4503,27 @@ var KIND_MAP = {
|
|
|
4409
4503
|
dash_dot: "DASH_DOT",
|
|
4410
4504
|
dash_dot_dot: "DASH_DOT_DOT"
|
|
4411
4505
|
};
|
|
4506
|
+
function quantizeBorderWidth(pt) {
|
|
4507
|
+
const mm = pt * 0.3528;
|
|
4508
|
+
const standardWidths = [0.1, 0.12, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 1, 1.5, 2, 3, 4, 5];
|
|
4509
|
+
let closest = standardWidths[0];
|
|
4510
|
+
let minDiff = Math.abs(mm - closest);
|
|
4511
|
+
for (let i = 1; i < standardWidths.length; i++) {
|
|
4512
|
+
const diff = Math.abs(mm - standardWidths[i]);
|
|
4513
|
+
if (diff < minDiff) {
|
|
4514
|
+
minDiff = diff;
|
|
4515
|
+
closest = standardWidths[i];
|
|
4516
|
+
}
|
|
4517
|
+
}
|
|
4518
|
+
let str = closest.toFixed(2);
|
|
4519
|
+
if (str.endsWith("0")) {
|
|
4520
|
+
str = str.slice(0, -1);
|
|
4521
|
+
}
|
|
4522
|
+
if (str.endsWith(".0")) {
|
|
4523
|
+
str = str.slice(0, -2);
|
|
4524
|
+
}
|
|
4525
|
+
return `${str} mm`;
|
|
4526
|
+
}
|
|
4412
4527
|
var BorderFillBank = class {
|
|
4413
4528
|
constructor() {
|
|
4414
4529
|
this.fills = [];
|
|
@@ -4421,7 +4536,7 @@ var BorderFillBank = class {
|
|
|
4421
4536
|
}
|
|
4422
4537
|
_strokeXml(tag, s) {
|
|
4423
4538
|
const type = s && s.kind !== "none" ? KIND_MAP[s.kind] ?? "SOLID" : "NONE";
|
|
4424
|
-
const w = s && s.kind !== "none" ?
|
|
4539
|
+
const w = s && s.kind !== "none" ? quantizeBorderWidth(s.pt) : "0.12 mm";
|
|
4425
4540
|
const c = s ? s.color.startsWith("#") ? s.color : `#${s.color}` : "#000000";
|
|
4426
4541
|
return `<hh:${tag} type="${type}" width="${w}" color="${c}"/>`;
|
|
4427
4542
|
}
|
|
@@ -4498,7 +4613,7 @@ function charPrKey(p) {
|
|
|
4498
4613
|
return `${p.b ? 1 : 0}|${p.i ? 1 : 0}|${p.u ? 1 : 0}|${p.s ? 1 : 0}|${p.pt ?? 10}|${p.color ?? "000000"}|${p.font ?? ""}|${p.bg ?? ""}`;
|
|
4499
4614
|
}
|
|
4500
4615
|
function paraPrKey(p) {
|
|
4501
|
-
return `${p.align ?? "left"}|${p.listOrd ?? ""}|${p.listLv ?? 0}|${p.indentPt ?? 0}|${p.firstLineIndentPt ?? 0}|${p.spaceBefore ?? 0}|${p.spaceAfter ?? 0}|${p.lineHeight ?? 0}|${p.styleId ?? ""}`;
|
|
4616
|
+
return `${p.align ?? "left"}|${p.verAlign ?? "baseline"}|${p.lineWrap ?? "break"}|${p.listOrd ?? ""}|${p.listLv ?? 0}|${p.indentPt ?? 0}|${p.leftMargin ?? 0}|${p.indentRightPt ?? 0}|${p.firstLineIndentPt ?? 0}|${p.spaceBefore ?? 0}|${p.spaceAfter ?? 0}|${p.lineHeight ?? 0}|${p.lineHeightFixed ?? 0}|${p.styleId ?? ""}`;
|
|
4502
4617
|
}
|
|
4503
4618
|
function registerCharPr(props, ctx) {
|
|
4504
4619
|
const key = charPrKey(props);
|
|
@@ -4522,20 +4637,45 @@ function registerCharPr(props, ctx) {
|
|
|
4522
4637
|
ctx.charPrMap.set(key, id);
|
|
4523
4638
|
return id;
|
|
4524
4639
|
}
|
|
4640
|
+
var ALIGN_MAP2 = {
|
|
4641
|
+
left: "LEFT",
|
|
4642
|
+
center: "CENTER",
|
|
4643
|
+
right: "RIGHT",
|
|
4644
|
+
justify: "JUSTIFY",
|
|
4645
|
+
distribute: "DISTRIBUTE",
|
|
4646
|
+
distribute_space: "DISTRIBUTE_SPACE"
|
|
4647
|
+
};
|
|
4648
|
+
var V_ALIGN_MAP = {
|
|
4649
|
+
baseline: "BASELINE",
|
|
4650
|
+
top: "TOP",
|
|
4651
|
+
center: "CENTER",
|
|
4652
|
+
bottom: "BOTTOM"
|
|
4653
|
+
};
|
|
4654
|
+
var LINE_WRAP_MAP = {
|
|
4655
|
+
break: "BREAK",
|
|
4656
|
+
squeeze: "SQUEEZE",
|
|
4657
|
+
keep: "KEEP"
|
|
4658
|
+
};
|
|
4525
4659
|
function registerParaPr(props, ctx) {
|
|
4526
4660
|
const key = paraPrKey(props);
|
|
4527
4661
|
const existing = ctx.paraPrMap.get(key);
|
|
4528
4662
|
if (existing !== void 0) return existing;
|
|
4529
4663
|
const id = ctx.paraPrs.length;
|
|
4664
|
+
const alignStr = props.align ? ALIGN_MAP2[props.align] ?? "LEFT" : "LEFT";
|
|
4665
|
+
const verAlignStr = props.verAlign ? V_ALIGN_MAP[props.verAlign] ?? "BASELINE" : "BASELINE";
|
|
4666
|
+
const lineWrapStr = props.lineWrap ? LINE_WRAP_MAP[props.lineWrap] ?? "BREAK" : "BREAK";
|
|
4530
4667
|
const def = {
|
|
4531
4668
|
id,
|
|
4532
|
-
align:
|
|
4533
|
-
|
|
4669
|
+
align: alignStr,
|
|
4670
|
+
verAlign: verAlignStr,
|
|
4671
|
+
lineWrap: lineWrapStr,
|
|
4672
|
+
leftHwp: Metric.ptToHwp(props.leftMargin ?? 0),
|
|
4534
4673
|
rightHwp: Metric.ptToHwp(props.indentRightPt ?? 0),
|
|
4535
4674
|
intentHwp: Metric.ptToHwp(props.firstLineIndentPt ?? 0),
|
|
4536
4675
|
prevHwp: Metric.ptToHwp(props.spaceBefore ?? 0),
|
|
4537
4676
|
nextHwp: Metric.ptToHwp(props.spaceAfter ?? 0),
|
|
4538
|
-
lineSpacing: props.lineHeight ? Math.round(props.lineHeight * 100) : 160
|
|
4677
|
+
lineSpacing: props.lineHeightFixed ? 0 : props.lineHeight ? Math.round(props.lineHeight * 100) : 160,
|
|
4678
|
+
lineSpacingFixed: props.lineHeightFixed ? Metric.ptToHwp(props.lineHeightFixed) : void 0
|
|
4539
4679
|
};
|
|
4540
4680
|
if (props.listOrd !== void 0) {
|
|
4541
4681
|
def.listType = props.listOrd ? "DIGIT" : "BULLET";
|
|
@@ -4640,8 +4780,8 @@ var HwpxEncoder = class extends BaseEncoder {
|
|
|
4640
4780
|
try {
|
|
4641
4781
|
const sheet = doc.kids[0];
|
|
4642
4782
|
const dims = normalizeDims(sheet?.dims ?? A4);
|
|
4643
|
-
const safeML = dims.ml
|
|
4644
|
-
const safeMR = dims.mr
|
|
4783
|
+
const safeML = dims.ml !== void 0 && dims.ml >= 0 ? dims.ml : 70.87;
|
|
4784
|
+
const safeMR = dims.mr !== void 0 && dims.mr >= 0 ? dims.mr : 70.87;
|
|
4645
4785
|
const availableWidth = Math.round(
|
|
4646
4786
|
Metric.ptToHwp(dims.wPt) - Metric.ptToHwp(safeML) - Metric.ptToHwp(safeMR)
|
|
4647
4787
|
);
|
|
@@ -4697,9 +4837,9 @@ var HwpxEncoder = class extends BaseEncoder {
|
|
|
4697
4837
|
mime: "application/xml"
|
|
4698
4838
|
},
|
|
4699
4839
|
{
|
|
4700
|
-
name: "META-INF/
|
|
4701
|
-
data: this.stringToBytes(
|
|
4702
|
-
mime: "application/
|
|
4840
|
+
name: "META-INF/manifest.xml",
|
|
4841
|
+
data: this.stringToBytes(MANIFEST_XML),
|
|
4842
|
+
mime: "application/xml"
|
|
4703
4843
|
},
|
|
4704
4844
|
{
|
|
4705
4845
|
name: "Contents/content.hpf",
|
|
@@ -4738,9 +4878,9 @@ var HwpxEncoder = class extends BaseEncoder {
|
|
|
4738
4878
|
}
|
|
4739
4879
|
}
|
|
4740
4880
|
};
|
|
4741
|
-
var VERSION_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><hv:HCFVersion xmlns:hv="http://www.
|
|
4742
|
-
var CONTAINER_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><ocf:container xmlns:ocf="urn:oasis:names:tc:opendocument:xmlns:container" xmlns:hpf="http://www.hancom.co.kr/schema/2011/hpf"><ocf:rootfiles><ocf:rootfile full-path="Contents/content.hpf" media-type="application/hwpml-package+xml"/><ocf:rootfile full-path="Preview/PrvText.txt" media-type="text/plain"
|
|
4743
|
-
var
|
|
4881
|
+
var VERSION_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><hv:HCFVersion xmlns:hv="http://www.hancom.co.kr/hwpml/2011/version" tagetApplication="WORDPROCESSOR" major="5" minor="0" micro="5" buildNumber="0" os="1" xmlVersion="1.4" application="Hancom Office Hangul" appVersion="9, 6, 1, 10097"/>`;
|
|
4882
|
+
var CONTAINER_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><ocf:container xmlns:ocf="urn:oasis:names:tc:opendocument:xmlns:container" xmlns:hpf="http://www.hancom.co.kr/schema/2011/hpf"><ocf:rootfiles><ocf:rootfile full-path="Contents/content.hpf" media-type="application/hwpml-package+xml"/><ocf:rootfile full-path="Preview/PrvText.txt" media-type="text/plain"/></ocf:rootfiles></ocf:container>`;
|
|
4883
|
+
var MANIFEST_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><odf:manifest xmlns:odf="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"/>`;
|
|
4744
4884
|
function buildContentHpf(ctx, meta) {
|
|
4745
4885
|
const title = esc(meta?.title ?? "");
|
|
4746
4886
|
const creator = esc(meta?.author ?? "text");
|
|
@@ -4766,6 +4906,18 @@ function buildNumberingsXml() {
|
|
|
4766
4906
|
function buildBulletsXml() {
|
|
4767
4907
|
return `<hh:bullets itemCnt="1"><hh:bullet id="1" charPrIDRef="0" start="1" numFormat="BULLET"><hh:paraHead level="1" numChar="•"/><hh:paraHead level="2" numChar="•"/><hh:paraHead level="3" numChar="•"/></hh:bullet></hh:bullets>`;
|
|
4768
4908
|
}
|
|
4909
|
+
function buildHeaderSecPrListXml(dims) {
|
|
4910
|
+
const wHwp = Metric.ptToHwp(dims.wPt);
|
|
4911
|
+
const hHwp = Metric.ptToHwp(dims.hPt);
|
|
4912
|
+
const ml = Metric.ptToHwp(dims.ml);
|
|
4913
|
+
const mr = Metric.ptToHwp(dims.mr);
|
|
4914
|
+
const mt = Metric.ptToHwp(dims.mt);
|
|
4915
|
+
const mb = Metric.ptToHwp(dims.mb);
|
|
4916
|
+
const headerZone = dims.headerPt !== void 0 && dims.headerPt > 0 ? Metric.ptToHwp(dims.headerPt) : 0;
|
|
4917
|
+
const footerZone = dims.footerPt !== void 0 && dims.footerPt > 0 ? Metric.ptToHwp(dims.footerPt) : 0;
|
|
4918
|
+
const pageBorderFill = `<hh:pageBorderFill type="BOTH" borderFillIDRef="1" textBorder="PAPER" headerInside="0" footerInside="0" fillArea="PAPER"><hh:offset left="1417" right="1417" top="1417" bottom="1417"/></hh:pageBorderFill><hh:pageBorderFill type="EVEN" borderFillIDRef="1" textBorder="PAPER" headerInside="0" footerInside="0" fillArea="PAPER"><hh:offset left="1417" right="1417" top="1417" bottom="1417"/></hh:pageBorderFill><hh:pageBorderFill type="ODD" borderFillIDRef="1" textBorder="PAPER" headerInside="0" footerInside="0" fillArea="PAPER"><hh:offset left="1417" right="1417" top="1417" bottom="1417"/></hh:pageBorderFill>`;
|
|
4919
|
+
return `<hh:secPrList itemCnt="1"><hh:secPr id="0" textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="0" memoShapeIDRef="0" textVerticalWidthHead="0" masterPageCnt="0"><hh:grid lineGrid="0" charGrid="0" wonggojiFormat="0"/><hh:startNum pageStartsOn="BOTH" page="0" pic="0" tbl="0" equation="0"/><hh:visibility hideFirstHeader="0" hideFirstFooter="0" hideFirstMasterPage="0" border="SHOW_ALL" fill="SHOW_ALL" hideFirstPageNum="0" hideFirstEmptyLine="0" showLineNumber="0"/><hh:lineNumberShape restartType="0" countBy="0" distance="0" startNumber="0"/><hh:pagePr landscape="WIDELY" width="${wHwp}" height="${hHwp}" gutterType="LEFT_ONLY"><hh:margin header="${headerZone}" footer="${footerZone}" gutter="0" left="${ml}" right="${mr}" top="${mt}" bottom="${mb}"/></hh:pagePr><hh:colPr id="" type="NEWSPAPER" layout="LEFT" colCount="1" sameSz="1" sameGap="0"/><hh:footNotePr><hh:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar="" supscript="1"/><hh:noteLine length="-1" type="SOLID" width="0.25 mm" color="#000000"/><hh:noteSpacing betweenNotes="283" belowLine="0" aboveLine="1000"/><hh:numbering type="CONTINUOUS" newNum="1"/><hh:placement place="EACH_COLUMN" beneathText="0"/></hh:footNotePr><hh:endNotePr><hh:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar="" supscript="1"/><hh:noteLine length="-1" type="SOLID" width="0.25 mm" color="#000000"/><hh:noteSpacing betweenNotes="0" belowLine="0" aboveLine="1000"/><hh:numbering type="CONTINUOUS" newNum="1"/><hh:placement place="END_OF_DOCUMENT" beneathText="0"/></hh:endNotePr>` + pageBorderFill + `</hh:secPr></hh:secPrList>`;
|
|
4920
|
+
}
|
|
4769
4921
|
function buildHeaderXml(dims, meta, ctx) {
|
|
4770
4922
|
const fontFacesXml = ctx.fontBank.toXml();
|
|
4771
4923
|
let charPrXml = "";
|
|
@@ -4779,51 +4931,17 @@ function buildHeaderXml(dims, meta, ctx) {
|
|
|
4779
4931
|
}
|
|
4780
4932
|
let paraPrXml = "";
|
|
4781
4933
|
for (const pp of ctx.paraPrs) {
|
|
4782
|
-
|
|
4934
|
+
const ver = pp.verAlign ?? "BASELINE";
|
|
4935
|
+
const wrap = pp.lineWrap ?? "BREAK";
|
|
4936
|
+
const lsType = pp.lineSpacingFixed !== void 0 ? "FIXED" : "PERCENT";
|
|
4937
|
+
const lsValue = pp.lineSpacingFixed !== void 0 ? pp.lineSpacingFixed : pp.lineSpacing;
|
|
4938
|
+
paraPrXml += `<hh:paraPr id="${pp.id}" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="0" suppressLineNumbers="0" checked="0"><hh:align horizontal="${pp.align}" vertical="${ver}"/><hh:heading type="NONE" idRef="0" level="0"/><hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="KEEP_WORD" widowOrphan="0" keepWithNext="0" keepLines="0" pageBreakBefore="0" lineWrap="${wrap}"/><hh:autoSpacing eAsianEng="0" eAsianNum="0"/><hh:margin><hc:intent value="${pp.intentHwp}" unit="HWPUNIT"/><hc:left value="${pp.leftHwp}" unit="HWPUNIT"/><hc:right value="${pp.rightHwp}" unit="HWPUNIT"/><hc:prev value="${pp.prevHwp}" unit="HWPUNIT"/><hc:next value="${pp.nextHwp}" unit="HWPUNIT"/></hh:margin><hh:lineSpacing type="${lsType}" value="${lsValue}" unit="HWPUNIT"/><hh:border borderFillIDRef="1" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/></hh:paraPr>`;
|
|
4783
4939
|
}
|
|
4784
4940
|
const borderFillXml = ctx.borderFillBank.toXml();
|
|
4785
4941
|
const stylesXml2 = `<hh:styles itemCnt="${ctx.hwpxStyles.length}">` + ctx.hwpxStyles.map(
|
|
4786
4942
|
(s) => `<hh:style id="${s.id}" type="PARA" name="${esc(s.name)}" engName="${esc(s.engName)}" paraPrIDRef="${s.paraPrIDRef}" charPrIDRef="${s.charPrIDRef}" nextStyleIDRef="0" langID="1042" lockForm="0"/>`
|
|
4787
4943
|
).join("") + `</hh:styles>`;
|
|
4788
|
-
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><hh:head ${NS} version="1.2" secCnt="1"><hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1"/><hh:refList>` + fontFacesXml + borderFillXml + `<hh:charProperties itemCnt="${ctx.charPrs.length}">${charPrXml}</hh:charProperties><hh:tabProperties itemCnt="1"><hh:tabPr id="0" autoTabLeft="0" autoTabRight="0"/></hh:tabProperties>` + buildNumberingsXml() + buildBulletsXml() + `<hh:paraProperties itemCnt="${ctx.paraPrs.length}">${paraPrXml}</hh:paraProperties>` + stylesXml2 + `</hh:refList
|
|
4789
|
-
<hh:layoutCompatibility>
|
|
4790
|
-
<hh:applyFontWeightToBold />
|
|
4791
|
-
<hh:useInnerUnderline />
|
|
4792
|
-
<hh:useLowercaseStrikeout />
|
|
4793
|
-
<hh:extendLineheightToOffset />
|
|
4794
|
-
<hh:treatQuotationAsLatin />
|
|
4795
|
-
<hh:doNotAlignWhitespaceOnRight />
|
|
4796
|
-
<hh:doNotAdjustWordInJustify />
|
|
4797
|
-
<hh:baseCharUnitOnEAsian />
|
|
4798
|
-
<hh:baseCharUnitOfIndentOnFirstChar />
|
|
4799
|
-
<hh:adjustLineheightToFont />
|
|
4800
|
-
<hh:adjustBaselineInFixedLinespacing />
|
|
4801
|
-
<hh:applyPrevspacingBeneathObject />
|
|
4802
|
-
<hh:applyNextspacingOfLastPara />
|
|
4803
|
-
<hh:adjustParaBorderfillToSpacing />
|
|
4804
|
-
<hh:connectParaBorderfillOfEqualBorder />
|
|
4805
|
-
<hh:adjustParaBorderOffsetWithBorder />
|
|
4806
|
-
<hh:extendLineheightToParaBorderOffset />
|
|
4807
|
-
<hh:applyParaBorderToOutside />
|
|
4808
|
-
<hh:applyMinColumnWidthTo1mm />
|
|
4809
|
-
<hh:applyTabPosBasedOnSegment />
|
|
4810
|
-
<hh:breakTabOverLine />
|
|
4811
|
-
<hh:adjustVertPosOfLine />
|
|
4812
|
-
<hh:doNotAlignLastForbidden />
|
|
4813
|
-
<hh:adjustMarginFromAdjustLineheight />
|
|
4814
|
-
<hh:baseLineSpacingOnLineGrid />
|
|
4815
|
-
<hh:applyCharSpacingToCharGrid />
|
|
4816
|
-
<hh:doNotApplyGridInHeaderFooter />
|
|
4817
|
-
<hh:applyExtendHeaderFooterEachSection />
|
|
4818
|
-
<hh:doNotApplyLinegridAtNoLinespacing />
|
|
4819
|
-
<hh:doNotAdjustEmptyAnchorLine />
|
|
4820
|
-
<hh:overlapBothAllowOverlap />
|
|
4821
|
-
<hh:extendVertLimitToPageMargins />
|
|
4822
|
-
<hh:doNotHoldAnchorOfTable />
|
|
4823
|
-
<hh:doNotFormattingAtBeneathAnchor />
|
|
4824
|
-
<hh:adjustBaselineOfObjectToBottom />
|
|
4825
|
-
</hh:layoutCompatibility>
|
|
4826
|
-
</hh:compatibleDocument><hh:docOption><hh:linkinfo path="" pageInherit="0" footnoteInherit="0"/></hh:docOption><hh:trackchageConfig flags="56"/></hh:head>`;
|
|
4944
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><hh:head ${NS} version="1.2" secCnt="1"><hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1"/><hh:refList>` + fontFacesXml + borderFillXml + `<hh:charProperties itemCnt="${ctx.charPrs.length}">${charPrXml}</hh:charProperties><hh:tabProperties itemCnt="1"><hh:tabPr id="0" autoTabLeft="0" autoTabRight="0"/></hh:tabProperties>` + buildNumberingsXml() + buildBulletsXml() + `<hh:paraProperties itemCnt="${ctx.paraPrs.length}">${paraPrXml}</hh:paraProperties>` + stylesXml2 + `</hh:refList>` + buildHeaderSecPrListXml(dims) + `<hh:compatibleDocument targetProgram="HWP201X"><hh:layoutCompatibility/></hh:compatibleDocument><hh:docOption><hh:linkinfo path="" pageInherit="0" footnoteInherit="0"/></hh:docOption><hh:trackchageConfig flags="56"/></hh:head>`;
|
|
4827
4945
|
}
|
|
4828
4946
|
function buildHeaderFooterRunXml(sheet, dims, ctx) {
|
|
4829
4947
|
const headers = sheet.headers || {};
|
|
@@ -4833,12 +4951,13 @@ function buildHeaderFooterRunXml(sheet, dims, ctx) {
|
|
|
4833
4951
|
const availW = ctx.availableWidth;
|
|
4834
4952
|
const mtHwp = Metric.ptToHwp(dims.mt);
|
|
4835
4953
|
const mbHwp = Metric.ptToHwp(dims.mb);
|
|
4836
|
-
const headerZoneH = dims.headerPt ?
|
|
4837
|
-
const footerZoneH = dims.footerPt ?
|
|
4954
|
+
const headerZoneH = dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 4252;
|
|
4955
|
+
const footerZoneH = dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 4252;
|
|
4838
4956
|
let inner = "";
|
|
4839
4957
|
const hideFirst = !!(headers.first || footers.first);
|
|
4840
4958
|
inner += `<hp:ctrl><hp:pageHiding hideHeader="${hideFirst ? 1 : 0}" hideFooter="${hideFirst ? 1 : 0}" hideMasterPage="0" hideBorder="0" hideFill="0" hidePageNum="0"/></hp:ctrl>`;
|
|
4841
4959
|
for (const [type, paras] of Object.entries(headers)) {
|
|
4960
|
+
if (!Array.isArray(paras) || paras.length === 0) continue;
|
|
4842
4961
|
const applyPageType = type === "even" ? "EVEN" : type === "default" || type === "first" ? "BOTH" : "ODD";
|
|
4843
4962
|
const savedId = ctx.nextElementId;
|
|
4844
4963
|
ctx.nextElementId = 0;
|
|
@@ -4847,6 +4966,7 @@ function buildHeaderFooterRunXml(sheet, dims, ctx) {
|
|
|
4847
4966
|
inner += `<hp:ctrl><hp:header id="1" applyPageType="${applyPageType}"><hp:subList id="" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="TOP" linkListIDRef="0" linkListNextIDRef="0" textWidth="${availW}" textHeight="${headerZoneH}" hasTextRef="0" hasNumRef="0">` + parasXml + `</hp:subList></hp:header></hp:ctrl>`;
|
|
4848
4967
|
}
|
|
4849
4968
|
for (const [type, paras] of Object.entries(footers)) {
|
|
4969
|
+
if (!Array.isArray(paras) || paras.length === 0) continue;
|
|
4850
4970
|
const applyPageType = type === "even" ? "EVEN" : type === "default" || type === "first" ? "BOTH" : "ODD";
|
|
4851
4971
|
const savedId = ctx.nextElementId;
|
|
4852
4972
|
ctx.nextElementId = 0;
|
|
@@ -4870,10 +4990,10 @@ function buildSectionXml(sheet, dims, ctx) {
|
|
|
4870
4990
|
for (let i = 0; i < kids.length; i++) {
|
|
4871
4991
|
const kid = kids[i];
|
|
4872
4992
|
const isFirst = i === 0;
|
|
4873
|
-
const curSecPr =
|
|
4993
|
+
const curSecPr = "";
|
|
4874
4994
|
const curHfRun = isFirst ? hfRunXml : "";
|
|
4875
4995
|
if (kid.tag === "para") {
|
|
4876
|
-
const { xml, nextVertPos } = encodeParaPositioned(
|
|
4996
|
+
const { xml, nextVertPos, hasPageBreak } = encodeParaPositioned(
|
|
4877
4997
|
kid,
|
|
4878
4998
|
ctx,
|
|
4879
4999
|
vertPos,
|
|
@@ -4884,7 +5004,7 @@ function buildSectionXml(sheet, dims, ctx) {
|
|
|
4884
5004
|
contentXml += xml;
|
|
4885
5005
|
vertPos = nextVertPos;
|
|
4886
5006
|
} else if (kid.tag === "grid") {
|
|
4887
|
-
const { xml, nextVertPos } = encodeGridPositioned(
|
|
5007
|
+
const { xml, nextVertPos, hasPageBreak } = encodeGridPositioned(
|
|
4888
5008
|
kid,
|
|
4889
5009
|
ctx,
|
|
4890
5010
|
vertPos,
|
|
@@ -4899,9 +5019,9 @@ function buildSectionXml(sheet, dims, ctx) {
|
|
|
4899
5019
|
const fs = 1e3;
|
|
4900
5020
|
const vs = 1600;
|
|
4901
5021
|
const { xml: linesegXml } = buildLinesegarray(" ", 0, fs, vs / (fs / 100), availWidth);
|
|
4902
|
-
contentXml = `<hp:p id="${ctx.nextElementId++}" paraPrIDRef="0" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0" paraTcId="0">` +
|
|
5022
|
+
contentXml = `<hp:p id="${ctx.nextElementId++}" paraPrIDRef="0" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0" paraTcId="0">` + hfRunXml + `<hp:run charPrIDRef="0" charTcId="0"><hp:t xml:space="preserve"> </hp:t></hp:run>` + linesegXml + `</hp:p>`;
|
|
4903
5023
|
}
|
|
4904
|
-
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><hs:sec ${NS} xmlns:hwpunitchar="http://www.hancom.co.kr/hwpml/2016/HwpUnitChar">${contentXml}</hs:sec>`;
|
|
5024
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><hs:sec ${NS} xmlns:hwpunitchar="http://www.hancom.co.kr/hwpml/2016/HwpUnitChar">${secPrXml}${contentXml}</hs:sec>`;
|
|
4905
5025
|
}
|
|
4906
5026
|
function buildSecPrXml(dims) {
|
|
4907
5027
|
const wHwp = Metric.ptToHwp(dims.wPt);
|
|
@@ -4910,24 +5030,62 @@ function buildSecPrXml(dims) {
|
|
|
4910
5030
|
const mr = Metric.ptToHwp(dims.mr);
|
|
4911
5031
|
const mt = Metric.ptToHwp(dims.mt);
|
|
4912
5032
|
const mb = Metric.ptToHwp(dims.mb);
|
|
4913
|
-
const headerZone = dims.headerPt ?
|
|
4914
|
-
const footerZone = dims.footerPt ?
|
|
5033
|
+
const headerZone = dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 0;
|
|
5034
|
+
const footerZone = dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 0;
|
|
4915
5035
|
const pageBorderFill = `<hp:pageBorderFill type="BOTH" borderFillIDRef="1" textBorder="PAPER" headerInside="0" footerInside="0" fillArea="PAPER"><hp:offset left="1417" right="1417" top="1417" bottom="1417"/></hp:pageBorderFill><hp:pageBorderFill type="EVEN" borderFillIDRef="1" textBorder="PAPER" headerInside="0" footerInside="0" fillArea="PAPER"><hp:offset left="1417" right="1417" top="1417" bottom="1417"/></hp:pageBorderFill><hp:pageBorderFill type="ODD" borderFillIDRef="1" textBorder="PAPER" headerInside="0" footerInside="0" fillArea="PAPER"><hp:offset left="1417" right="1417" top="1417" bottom="1417"/></hp:pageBorderFill>`;
|
|
4916
|
-
return `<hp:secPr id="0" textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="0" 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:lineNumberShape restartType="0" countBy="0" distance="0" startNumber="0"/><hp:pagePr landscape="
|
|
5036
|
+
return `<hp:secPr id="0" textDirection="HORIZONTAL" spaceColumns="1134" tabStop="8000" outlineShapeIDRef="0" 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:lineNumberShape restartType="0" countBy="0" distance="0" startNumber="0"/><hp:pagePr landscape="WIDELY" width="${wHwp}" height="${hHwp}" gutterType="LEFT_ONLY"><hp:margin header="${headerZone}" footer="${footerZone}" gutter="0" left="${ml}" right="${mr}" top="${mt}" bottom="${mb}"/></hp:pagePr><hp:colPr id="" type="NEWSPAPER" layout="LEFT" colCount="1" sameSz="1" sameGap="0"/><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar="" supscript="1"/><hp:noteLine length="-1" type="SOLID" width="0.25 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="0" aboveLine="1000"/><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="1"/><hp:noteLine length="-1" type="SOLID" width="0.25 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="0" aboveLine="1000"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr>` + pageBorderFill + `</hp:secPr>`;
|
|
4917
5037
|
}
|
|
4918
5038
|
function buildLinesegarray(text, vertPosStart, fontSize, lineSpacingPct, horzSize) {
|
|
4919
5039
|
const vertsizeLine = Math.round(fontSize * lineSpacingPct / 100);
|
|
4920
5040
|
const spacing = vertsizeLine - fontSize;
|
|
4921
5041
|
const baseline = Math.round(fontSize * 0.83);
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
5042
|
+
if (text.length === 0) {
|
|
5043
|
+
const xml = `<hp:linesegarray><hp:lineseg textpos="0" vertpos="${vertPosStart}" vertsize="${vertsizeLine}" textheight="${fontSize}" baseline="${baseline}" spacing="${spacing}" horzpos="0" horzsize="${horzSize}" flags="${LINESEG_FLAGS_FIRST}"/></hp:linesegarray>`;
|
|
5044
|
+
return { xml, totalHeight: vertsizeLine };
|
|
5045
|
+
}
|
|
5046
|
+
const lines = [];
|
|
5047
|
+
let currentLineWidth = 0;
|
|
5048
|
+
let lineStartIdx = 0;
|
|
5049
|
+
for (let i = 0; i < text.length; i++) {
|
|
5050
|
+
const charCode = text.charCodeAt(i);
|
|
5051
|
+
if (charCode === 10 || charCode === 13) {
|
|
5052
|
+
lines.push({ startPos: lineStartIdx, width: currentLineWidth });
|
|
5053
|
+
lineStartIdx = i + 1;
|
|
5054
|
+
currentLineWidth = 0;
|
|
5055
|
+
continue;
|
|
5056
|
+
}
|
|
5057
|
+
let charW = fontSize * 0.55;
|
|
5058
|
+
if (charCode >= 44032 && charCode <= 55203) {
|
|
5059
|
+
charW = fontSize;
|
|
5060
|
+
} else if (charCode >= 12592 && charCode <= 12687) {
|
|
5061
|
+
charW = fontSize;
|
|
5062
|
+
} else if (charCode >= 19968 && charCode <= 40959) {
|
|
5063
|
+
charW = fontSize;
|
|
5064
|
+
} else if (charCode >= 65 && charCode <= 90) {
|
|
5065
|
+
charW = fontSize * 0.65;
|
|
5066
|
+
} else if (charCode === 32) {
|
|
5067
|
+
charW = fontSize * 0.32;
|
|
5068
|
+
} else if (charCode > 255) {
|
|
5069
|
+
charW = fontSize;
|
|
5070
|
+
} else {
|
|
5071
|
+
charW = fontSize * 0.42;
|
|
5072
|
+
}
|
|
5073
|
+
if (currentLineWidth + charW > horzSize && i > lineStartIdx) {
|
|
5074
|
+
lines.push({ startPos: lineStartIdx, width: currentLineWidth });
|
|
5075
|
+
lineStartIdx = i;
|
|
5076
|
+
currentLineWidth = charW;
|
|
5077
|
+
} else {
|
|
5078
|
+
currentLineWidth += charW;
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
lines.push({ startPos: lineStartIdx, width: currentLineWidth });
|
|
5082
|
+
const lineCount = lines.length;
|
|
4926
5083
|
const linesegParts = [];
|
|
4927
5084
|
for (let i = 0; i < lineCount; i++) {
|
|
4928
5085
|
const flags = i === 0 ? LINESEG_FLAGS_FIRST : LINESEG_FLAGS_OTHER;
|
|
5086
|
+
const textpos = lines[i].startPos;
|
|
4929
5087
|
linesegParts.push(
|
|
4930
|
-
`<hp:lineseg textpos="${
|
|
5088
|
+
`<hp:lineseg textpos="${textpos}" vertpos="${vertPosStart + i * vertsizeLine}" vertsize="${vertsizeLine}" textheight="${fontSize}" baseline="${baseline}" spacing="${spacing}" horzpos="0" horzsize="${horzSize}" flags="${flags}"/>`
|
|
4931
5089
|
);
|
|
4932
5090
|
}
|
|
4933
5091
|
return {
|
|
@@ -4940,7 +5098,13 @@ function extractParaText(para) {
|
|
|
4940
5098
|
const walk = (kids) => {
|
|
4941
5099
|
for (const k of kids) {
|
|
4942
5100
|
if (k.tag === "span") {
|
|
4943
|
-
for (const c of k.kids)
|
|
5101
|
+
for (const c of k.kids) {
|
|
5102
|
+
if (c.tag === "txt") {
|
|
5103
|
+
text += c.content;
|
|
5104
|
+
} else if (c.tag === "br") {
|
|
5105
|
+
text += "\n";
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
4944
5108
|
} else if (k.tag === "link") {
|
|
4945
5109
|
walk(k.kids);
|
|
4946
5110
|
}
|
|
@@ -4999,7 +5163,7 @@ function encodeParaPositioned(para, ctx, vertPos, secPr = "", availWidth, hfRun
|
|
|
4999
5163
|
(k) => k.tag === "span" && k.kids.some((c) => c.tag === "pb")
|
|
5000
5164
|
);
|
|
5001
5165
|
const xml = `<hp:p id="${ctx.nextElementId++}" paraPrIDRef="${paraPrId}" styleIDRef="${styleIDRef}" pageBreak="${hasPageBreak ? 1 : 0}" columnBreak="0" merged="0" paraTcId="0">` + secPr + hfRun + runsXml + linesegXml + `</hp:p>`;
|
|
5002
|
-
return { xml, nextVertPos: vertPos + totalHeight };
|
|
5166
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak };
|
|
5003
5167
|
}
|
|
5004
5168
|
function encodeTablePara(para, grid, ctx, vertPos, secPr, hfRun) {
|
|
5005
5169
|
const paraPrId = ctx.paraPrMap.get(paraPrKey(para.props)) ?? 0;
|
|
@@ -5009,8 +5173,12 @@ function encodeTablePara(para, grid, ctx, vertPos, secPr, hfRun) {
|
|
|
5009
5173
|
const baseline = 850;
|
|
5010
5174
|
const spacing = Math.max(0, totalHeight - fontSize);
|
|
5011
5175
|
const linesegXml = `<hp:linesegarray><hp:lineseg textpos="0" vertpos="${vertPos}" vertsize="${totalHeight}" textheight="${fontSize}" baseline="${baseline}" spacing="${spacing}" horzpos="0" horzsize="${ctx.availableWidth}" flags="1441792"/></hp:linesegarray>`;
|
|
5012
|
-
const
|
|
5013
|
-
|
|
5176
|
+
const hasPageBreak = para.kids.some(
|
|
5177
|
+
(k) => k.tag === "span" && k.kids.some((c) => c.tag === "pb")
|
|
5178
|
+
);
|
|
5179
|
+
const runId = ctx.nextElementId++;
|
|
5180
|
+
const xml = `<hp:p id="${ctx.nextElementId++}" paraPrIDRef="${paraPrId}" styleIDRef="0" pageBreak="${hasPageBreak ? 1 : 0}" columnBreak="0" merged="0" paraTcId="0">` + secPr + `<hp:run id="${runId}" charPrIDRef="0" charTcId="0">` + gridXml + `</hp:run>` + hfRun + linesegXml + `</hp:p>`;
|
|
5181
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak };
|
|
5014
5182
|
}
|
|
5015
5183
|
function encodeCodeBlockPositioned(para, ctx, vertPos, secPr, fontSize, spacing, vertSize) {
|
|
5016
5184
|
const codeBfId = ctx.borderFillBank.addUniform(
|
|
@@ -5031,7 +5199,7 @@ function encodeCodeBlockPositioned(para, ctx, vertPos, secPr, fontSize, spacing,
|
|
|
5031
5199
|
ctx.availableWidth
|
|
5032
5200
|
);
|
|
5033
5201
|
const xml = `<hp:p id="${ctx.nextElementId++}" paraPrIDRef="0" styleIDRef="0" paraTcId="0">` + secPr + `<hp:run charPrIDRef="0" charTcId="0"><hp:tbl id="${ctx.nextElementId++}" zOrder="0" numberingType="TABLE" textWrap="TOP_AND_BOTTOM" textFlow="BOTH_SIDES" lock="0" dropcapstyle="None" pageBreak="NONE" rowCnt="1" colCnt="1" cellSpacing="0" borderFillIDRef="${codeBfId}" noAdjust="0"><hp:sz width="${cellW}" widthRelTo="ABSOLUTE" height="0" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="1" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="138" right="138" top="138" bottom="138"/><hp:inMargin left="138" right="138" top="138" bottom="138"/><hp:tr><hp:tc name="" header="0" hasMargin="1" protect="0" editable="0" dirty="0" borderFillIDRef="${codeBfId}"><hp:subList id="${subListId}" textDirection="HORIZONTAL" lineWrap="BREAK" vertAlign="CENTER" linkListIDRef="0" linkListNextIDRef="0" textWidth="0" textHeight="0" hasTextRef="0" hasNumRef="0">` + innerXml + `</hp:subList><hp:cellAddr colAddr="0" rowAddr="0"/><hp:cellSpan colSpan="1" rowSpan="1"/><hp:cellSz width="${cellW}" height="0"/><hp:cellMargin left="283" right="283" top="141" bottom="141"/></hp:tc></hp:tr></hp:tbl><hp:t xml:space="preserve"> </hp:t></hp:run>` + linesegXml + `</hp:p>`;
|
|
5034
|
-
return { xml, nextVertPos: vertPos + totalHeight };
|
|
5202
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak: false };
|
|
5035
5203
|
}
|
|
5036
5204
|
function encodeParaKids(kids, ctx) {
|
|
5037
5205
|
let xml = "";
|
|
@@ -5080,8 +5248,7 @@ function encodeRunInner(span) {
|
|
|
5080
5248
|
const content = esc(kid.content);
|
|
5081
5249
|
if (content) xml += `<hp:t xml:space="preserve">${content}</hp:t>`;
|
|
5082
5250
|
} else if (kid.tag === "br") {
|
|
5083
|
-
xml += `<hp:
|
|
5084
|
-
</hp:t>`;
|
|
5251
|
+
xml += `<hp:br/>`;
|
|
5085
5252
|
} else if (kid.tag === "pagenum") {
|
|
5086
5253
|
const fmt = kid.format === "roman" ? "ROMAN_LOWER" : kid.format === "romanCaps" ? "ROMAN_UPPER" : "DIGIT";
|
|
5087
5254
|
xml += `<hp:pageNum pageStartsOn="BOTH" formatType="${fmt}"/>`;
|
|
@@ -5162,8 +5329,9 @@ function encodeGridPositioned(grid, ctx, vertPos, secPr = "", hfRun = "") {
|
|
|
5162
5329
|
const baseline = Math.round(fontSize * 0.83);
|
|
5163
5330
|
const spacing = Math.max(0, totalHeight - fontSize);
|
|
5164
5331
|
const linesegXml = `<hp:linesegarray><hp:lineseg textpos="0" vertpos="${vertPos}" vertsize="${totalHeight}" textheight="${fontSize}" baseline="${baseline}" spacing="${spacing}" horzpos="0" horzsize="${ctx.availableWidth}" flags="${LINESEG_FLAGS_FIRST}"/></hp:linesegarray>`;
|
|
5165
|
-
const
|
|
5166
|
-
|
|
5332
|
+
const runId = ctx.nextElementId++;
|
|
5333
|
+
const xml = `<hp:p id="${ctx.nextElementId++}" paraPrIDRef="0" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0" paraTcId="0">` + secPr + hfRun + `<hp:run id="${runId}" charPrIDRef="0" charTcId="0">` + gridXml + `</hp:run>` + linesegXml + `</hp:p>`;
|
|
5334
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak: false };
|
|
5167
5335
|
}
|
|
5168
5336
|
function buildGridXml(grid, ctx) {
|
|
5169
5337
|
const rowCount = grid.kids.length;
|
|
@@ -5551,6 +5719,40 @@ function stylesXml() {
|
|
|
5551
5719
|
</w:pPr></w:pPrDefault>
|
|
5552
5720
|
</w:docDefaults>
|
|
5553
5721
|
<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/></w:style>
|
|
5722
|
+
<w:style w:type="paragraph" w:styleId="0"><w:name w:val="\uBC14\uD0D5\uAE00"/><w:basedOn w:val="Normal"/></w:style>
|
|
5723
|
+
<w:style w:type="paragraph" w:styleId="1"><w:name w:val="\uBCF8\uBB38"/><w:basedOn w:val="Normal"/></w:style>
|
|
5724
|
+
<w:style w:type="paragraph" w:styleId="2"><w:name w:val="\uAC1C\uC694 1"/><w:basedOn w:val="Normal"/></w:style>
|
|
5725
|
+
<w:style w:type="paragraph" w:styleId="3"><w:name w:val="\uAC1C\uC694 2"/><w:basedOn w:val="Normal"/></w:style>
|
|
5726
|
+
<w:style w:type="paragraph" w:styleId="4"><w:name w:val="\uAC1C\uC694 3"/><w:basedOn w:val="Normal"/></w:style>
|
|
5727
|
+
<w:style w:type="paragraph" w:styleId="5"><w:name w:val="\uAC1C\uC694 4"/><w:basedOn w:val="Normal"/></w:style>
|
|
5728
|
+
<w:style w:type="paragraph" w:styleId="6"><w:name w:val="\uAC1C\uC694 5"/><w:basedOn w:val="Normal"/></w:style>
|
|
5729
|
+
<w:style w:type="paragraph" w:styleId="7"><w:name w:val="\uAC1C\uC694 6"/><w:basedOn w:val="Normal"/></w:style>
|
|
5730
|
+
<w:style w:type="paragraph" w:styleId="8"><w:name w:val="\uAC1C\uC694 7"/><w:basedOn w:val="Normal"/></w:style>
|
|
5731
|
+
<w:style w:type="paragraph" w:styleId="9"><w:name w:val="\uAC1C\uC694 8"/><w:basedOn w:val="Normal"/></w:style>
|
|
5732
|
+
<w:style w:type="paragraph" w:styleId="10"><w:name w:val="\uAC1C\uC694 9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5733
|
+
<w:style w:type="paragraph" w:styleId="11"><w:name w:val="\uAC1C\uC694 10"/><w:basedOn w:val="Normal"/></w:style>
|
|
5734
|
+
<w:style w:type="paragraph" w:styleId="12"><w:name w:val="\uCABD \uBC88\uD638"/><w:basedOn w:val="Normal"/></w:style>
|
|
5735
|
+
<w:style w:type="paragraph" w:styleId="13"><w:name w:val="\uBA38\uB9AC\uB9D0"/><w:basedOn w:val="Normal"/></w:style>
|
|
5736
|
+
<w:style w:type="paragraph" w:styleId="14"><w:name w:val="\uAC01\uC8FC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5737
|
+
<w:style w:type="paragraph" w:styleId="15"><w:name w:val="\uBBF8\uC8FC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5738
|
+
<w:style w:type="paragraph" w:styleId="16"><w:name w:val="\uBA54\uBAA8"/><w:basedOn w:val="Normal"/></w:style>
|
|
5739
|
+
<w:style w:type="paragraph" w:styleId="17"><w:name w:val="\uCC28\uB840 \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5740
|
+
<w:style w:type="paragraph" w:styleId="18"><w:name w:val="\uCC28\uB840 1"/><w:basedOn w:val="Normal"/></w:style>
|
|
5741
|
+
<w:style w:type="paragraph" w:styleId="19"><w:name w:val="\uCC28\uB840 2"/><w:basedOn w:val="Normal"/></w:style>
|
|
5742
|
+
<w:style w:type="paragraph" w:styleId="20"><w:name w:val="\uCC28\uB840 3"/><w:basedOn w:val="Normal"/></w:style>
|
|
5743
|
+
<w:style w:type="paragraph" w:styleId="21"><w:name w:val="\uBCF8\uBB38 \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5744
|
+
<w:style w:type="paragraph" w:styleId="22"><w:name w:val="\uADF8\uB9BC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5745
|
+
<w:style w:type="paragraph" w:styleId="23"><w:name w:val="\uD45C"/><w:basedOn w:val="Normal"/></w:style>
|
|
5746
|
+
<w:style w:type="paragraph" w:styleId="24"><w:name w:val="\uC218\uC2DD"/><w:basedOn w:val="Normal"/></w:style>
|
|
5747
|
+
<w:style w:type="paragraph" w:styleId="25"><w:name w:val="\uC778\uC6A9\uBB38"/><w:basedOn w:val="Normal"/></w:style>
|
|
5748
|
+
<w:style w:type="paragraph" w:styleId="26"><w:name w:val="\uB0A0\uC9DC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5749
|
+
<w:style w:type="paragraph" w:styleId="27"><w:name w:val="\uBC1C\uC2E0\uBA85\uC758"/><w:basedOn w:val="Normal"/></w:style>
|
|
5750
|
+
<w:style w:type="paragraph" w:styleId="28"><w:name w:val="\uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5751
|
+
<w:style w:type="paragraph" w:styleId="29"><w:name w:val="\uBD80\uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5752
|
+
<w:style w:type="paragraph" w:styleId="30"><w:name w:val="\uBB38\uB2E8 \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5753
|
+
<w:style w:type="paragraph" w:styleId="31"><w:name w:val="MEMO"/><w:basedOn w:val="Normal"/></w:style>
|
|
5754
|
+
<w:style w:type="paragraph" w:styleId="32"><w:name w:val="\uAC1C\uC694"/><w:basedOn w:val="Normal"/></w:style>
|
|
5755
|
+
<w:style w:type="paragraph" w:styleId="33"><w:name w:val="\uD45C \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5554
5756
|
<w:style w:type="paragraph" w:styleId="Heading1"><w:name w:val="heading 1"/><w:basedOn w:val="Normal"/><w:pPr><w:keepNext/><w:outlineLvl w:val="0"/></w:pPr><w:rPr><w:b/><w:sz w:val="44"/><w:szCs w:val="44"/></w:rPr></w:style>
|
|
5555
5757
|
<w:style w:type="paragraph" w:styleId="Heading2"><w:name w:val="heading 2"/><w:basedOn w:val="Normal"/><w:pPr><w:keepNext/><w:outlineLvl w:val="1"/></w:pPr><w:rPr><w:b/><w:sz w:val="36"/><w:szCs w:val="36"/></w:rPr></w:style>
|
|
5556
5758
|
<w:style w:type="paragraph" w:styleId="Heading3"><w:name w:val="heading 3"/><w:basedOn w:val="Normal"/><w:pPr><w:keepNext/><w:outlineLvl w:val="2"/></w:pPr><w:rPr><w:b/><w:sz w:val="28"/><w:szCs w:val="28"/></w:rPr></w:style>
|
|
@@ -5640,7 +5842,12 @@ function encodeContent(node, ctx, dims) {
|
|
|
5640
5842
|
}
|
|
5641
5843
|
function encodeParaInner(para, ctx) {
|
|
5642
5844
|
const align = para.props.align ?? "left";
|
|
5643
|
-
|
|
5845
|
+
let headStyle = "";
|
|
5846
|
+
if (para.props.hwpStyleId !== void 0) {
|
|
5847
|
+
headStyle = `<w:pStyle w:val="${para.props.hwpStyleId}"/>`;
|
|
5848
|
+
} else if (para.props.heading) {
|
|
5849
|
+
headStyle = `<w:pStyle w:val="Heading${para.props.heading}"/>`;
|
|
5850
|
+
}
|
|
5644
5851
|
let numPr = "";
|
|
5645
5852
|
if (para.props.listOrd !== void 0) {
|
|
5646
5853
|
const numId = para.props.listOrd ? 2 : 1;
|
|
@@ -5679,6 +5886,10 @@ function encodeParaInner(para, ctx) {
|
|
|
5679
5886
|
const runs = para.kids.map((k) => {
|
|
5680
5887
|
if (k.tag === "span") return encodeRun(k, ctx);
|
|
5681
5888
|
if (k.tag === "img") return encodeImage2(k, ctx);
|
|
5889
|
+
if (k.tag === "pagenum") {
|
|
5890
|
+
const instr = k.format === "total" ? " NUMPAGES " : " PAGE ";
|
|
5891
|
+
return `<w:r><w:fldChar w:fldCharType="begin"/></w:r><w:r><w:instrText>${instr}</w:instrText></w:r><w:r><w:fldChar w:fldCharType="separate"/></w:r><w:r><w:t>1</w:t></w:r><w:r><w:fldChar w:fldCharType="end"/></w:r>`;
|
|
5892
|
+
}
|
|
5682
5893
|
return "";
|
|
5683
5894
|
}).join("");
|
|
5684
5895
|
return ` <w:p>
|
|
@@ -5715,8 +5926,9 @@ function encodeRun(span, _ctx) {
|
|
|
5715
5926
|
);
|
|
5716
5927
|
}
|
|
5717
5928
|
} else if (kid.tag === "pagenum") {
|
|
5929
|
+
const instr = kid.format === "total" ? " NUMPAGES " : " PAGE ";
|
|
5718
5930
|
parts.push(
|
|
5719
|
-
`<w:r><w:rPr>${rPr.join("")}</w:rPr><w:fldChar w:fldCharType="begin"/></w:r><w:r><w:rPr>${rPr.join("")}</w:rPr><w:instrText
|
|
5931
|
+
`<w:r><w:rPr>${rPr.join("")}</w:rPr><w:fldChar w:fldCharType="begin"/></w:r><w:r><w:rPr>${rPr.join("")}</w:rPr><w:instrText>${instr}</w:instrText></w:r><w:r><w:rPr>${rPr.join("")}</w:rPr><w:fldChar w:fldCharType="separate"/></w:r><w:r><w:rPr>${rPr.join("")}</w:rPr><w:t>1</w:t></w:r><w:r><w:rPr>${rPr.join("")}</w:rPr><w:fldChar w:fldCharType="end"/></w:r>`
|
|
5720
5932
|
);
|
|
5721
5933
|
} else if (kid.tag === "br") {
|
|
5722
5934
|
parts.push(`<w:r><w:br/></w:r>`);
|
|
@@ -6506,10 +6718,11 @@ var BufWriter = class {
|
|
|
6506
6718
|
};
|
|
6507
6719
|
function mkRec(tag, level, data) {
|
|
6508
6720
|
const sz = data.length;
|
|
6509
|
-
const
|
|
6510
|
-
const
|
|
6721
|
+
const isLarge = sz >= 4095;
|
|
6722
|
+
const enc = isLarge ? 4095 : sz;
|
|
6723
|
+
const hdr = ((enc & 4095) * 1048576 | (level & 1023) << 10 | tag & 1023) >>> 0;
|
|
6511
6724
|
const w = new BufWriter().u32(hdr);
|
|
6512
|
-
if (
|
|
6725
|
+
if (isLarge) w.u32(sz);
|
|
6513
6726
|
w.bytes(data);
|
|
6514
6727
|
return w.build();
|
|
6515
6728
|
}
|
|
@@ -6824,7 +7037,7 @@ function buildDocInfoStream(bank, images = []) {
|
|
|
6824
7037
|
return concatU8(chunks);
|
|
6825
7038
|
}
|
|
6826
7039
|
function mkPageDef(dims) {
|
|
6827
|
-
return new BufWriter().u32(Metric.ptToHwp(dims.wPt)).u32(Metric.ptToHwp(dims.hPt)).u32(Metric.ptToHwp(dims.ml)).u32(Metric.ptToHwp(dims.mr)).u32(Metric.ptToHwp(dims.mt)).u32(Metric.ptToHwp(dims.mb)).
|
|
7040
|
+
return new BufWriter().u32(Metric.ptToHwp(dims.wPt)).u32(Metric.ptToHwp(dims.hPt)).u32(Metric.ptToHwp(dims.ml)).u32(Metric.ptToHwp(dims.mr)).u32(Metric.ptToHwp(dims.mt)).u32(Metric.ptToHwp(dims.mb)).u32(dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 0).u32(dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 0).u32(0).u32(dims.orient === "landscape" ? 1 : 0).build();
|
|
6828
7041
|
}
|
|
6829
7042
|
function mkParaHeader(nchars, ctrlMask, psId, csCount, lineAlignCount = 0, instanceId = 0) {
|
|
6830
7043
|
return new BufWriter().u32(nchars).u32(ctrlMask).u16(psId).u8(0).u8(0).u16(csCount).u16(0).u16(lineAlignCount).u32(instanceId).u16(0).build();
|
|
@@ -7025,7 +7238,7 @@ function encodePara3(para, bank, lv, instanceId, availWidthHwp, mask = 0, vertPo
|
|
|
7025
7238
|
];
|
|
7026
7239
|
}
|
|
7027
7240
|
function mkTableCtrl(wHwp, hHwp, instanceId, align = "left") {
|
|
7028
|
-
const alignFlags = { left: 0, center: 1, right: 2, justify: 3 }[align] ?? 0;
|
|
7241
|
+
const alignFlags = { left: 0, center: 1, right: 2, justify: 3, distribute: 0, distribute_space: 0 }[align] ?? 0;
|
|
7029
7242
|
return new BufWriter().u32(CTRL_TABLE2).u32(136978961).i32(0).i32(0).u32(wHwp).u32(hHwp).i32(7).u16(140).u16(140).u16(140).u16(140).u32(instanceId).i32(alignFlags).u16(0).build();
|
|
7030
7243
|
}
|
|
7031
7244
|
function mkTableRecord(rowCnt, colCnt, rowHwp, bfId) {
|
|
@@ -7116,7 +7329,7 @@ function encodeGrid4(grid, bank, lv, idGen, availWidthHwp) {
|
|
|
7116
7329
|
const cellWidthHwp = Metric.ptToHwp(cwPt[c] ?? defColPt);
|
|
7117
7330
|
for (const para of paras) {
|
|
7118
7331
|
records.push(
|
|
7119
|
-
...encodePara3(para, bank, lv +
|
|
7332
|
+
...encodePara3(para, bank, lv + 1, idGen(), cellWidthHwp)
|
|
7120
7333
|
);
|
|
7121
7334
|
}
|
|
7122
7335
|
}
|
|
@@ -7358,6 +7571,7 @@ function buildHwpFileHeader() {
|
|
|
7358
7571
|
}
|
|
7359
7572
|
function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = []) {
|
|
7360
7573
|
const SS = 512;
|
|
7574
|
+
const MSS = 64;
|
|
7361
7575
|
const ENDOFCHAIN = 4294967294;
|
|
7362
7576
|
const FREESECT = 4294967295;
|
|
7363
7577
|
const FATSECT = 4294967293;
|
|
@@ -7366,71 +7580,150 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7366
7580
|
`FileHeader \uD06C\uAE30 \uBD80\uC871: ${fileHeaderData.length} (\uCD5C\uC18C 256)`
|
|
7367
7581
|
);
|
|
7368
7582
|
}
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7583
|
+
const streams = [];
|
|
7584
|
+
streams.push({
|
|
7585
|
+
name: "FileHeader",
|
|
7586
|
+
data: fileHeaderData,
|
|
7587
|
+
dirIdx: 1,
|
|
7588
|
+
isMini: fileHeaderData.length < 4096
|
|
7589
|
+
});
|
|
7590
|
+
streams.push({
|
|
7591
|
+
name: "DocInfo",
|
|
7592
|
+
data: docInfoData,
|
|
7593
|
+
dirIdx: 2,
|
|
7594
|
+
isMini: docInfoData.length < 4096
|
|
7595
|
+
});
|
|
7596
|
+
streams.push({
|
|
7597
|
+
name: "Section0",
|
|
7598
|
+
data: section0Data,
|
|
7599
|
+
dirIdx: 4,
|
|
7600
|
+
isMini: section0Data.length < 4096
|
|
7601
|
+
});
|
|
7602
|
+
for (let i = 0; i < binImages.length; i++) {
|
|
7603
|
+
const img = binImages[i];
|
|
7604
|
+
const name = `BIN${String(img.id).padStart(4, "0")}.${img.ext}`;
|
|
7605
|
+
streams.push({
|
|
7606
|
+
name,
|
|
7607
|
+
data: img.data,
|
|
7608
|
+
dirIdx: 6 + i,
|
|
7609
|
+
isMini: img.data.length < 4096
|
|
7610
|
+
});
|
|
7611
|
+
}
|
|
7612
|
+
const miniStreams = streams.filter((s) => s.isMini);
|
|
7613
|
+
const miniSectorList = [];
|
|
7614
|
+
let miniStreamDataLength = 0;
|
|
7615
|
+
for (const s of miniStreams) {
|
|
7616
|
+
const startSec = miniStreamDataLength / MSS;
|
|
7617
|
+
s.startSec = startSec;
|
|
7618
|
+
const len = s.data.length;
|
|
7619
|
+
const numMiniSecs = Math.ceil(len / MSS);
|
|
7620
|
+
for (let i = 0; i < numMiniSecs; i++) {
|
|
7621
|
+
const curSec2 = startSec + i;
|
|
7622
|
+
const nextSec = i === numMiniSecs - 1 ? ENDOFCHAIN : curSec2 + 1;
|
|
7623
|
+
while (miniSectorList.length <= curSec2) {
|
|
7624
|
+
miniSectorList.push(FREESECT);
|
|
7625
|
+
}
|
|
7626
|
+
miniSectorList[curSec2] = nextSec;
|
|
7627
|
+
}
|
|
7628
|
+
miniStreamDataLength += numMiniSecs * MSS;
|
|
7629
|
+
}
|
|
7630
|
+
const miniStreamData = new Uint8Array(miniStreamDataLength);
|
|
7631
|
+
let miniStreamOffset = 0;
|
|
7632
|
+
for (const s of miniStreams) {
|
|
7633
|
+
miniStreamData.set(s.data, miniStreamOffset);
|
|
7634
|
+
miniStreamOffset += Math.ceil(s.data.length / MSS) * MSS;
|
|
7635
|
+
}
|
|
7636
|
+
const regularStreams = streams.filter((s) => !s.isMini);
|
|
7637
|
+
const regPads = regularStreams.map((s) => {
|
|
7638
|
+
const len = s.data.length;
|
|
7639
|
+
const n = Math.ceil(Math.max(len, 1) / SS) * SS;
|
|
7372
7640
|
const out2 = new Uint8Array(n);
|
|
7373
|
-
out2.set(
|
|
7641
|
+
out2.set(s.data);
|
|
7374
7642
|
return out2;
|
|
7375
|
-
}
|
|
7376
|
-
const
|
|
7377
|
-
const diPad = padSector(docInfoData);
|
|
7378
|
-
const s0Pad = padSector(section0Data);
|
|
7379
|
-
const imgPads = binImages.map((img) => padSector(img.data));
|
|
7380
|
-
const fhN = fhPad.length / SS;
|
|
7381
|
-
const diN = diPad.length / SS;
|
|
7382
|
-
const s0N = s0Pad.length / SS;
|
|
7383
|
-
const imgNs = imgPads.map((p) => p.length / SS);
|
|
7384
|
-
const totalImgN = imgNs.reduce((s, n) => s + n, 0);
|
|
7643
|
+
});
|
|
7644
|
+
const regNs = regPads.map((p) => p.length / SS);
|
|
7385
7645
|
const numDirEntries = 5 + (binImages.length > 0 ? 1 + binImages.length : 0);
|
|
7386
|
-
const dirN = Math.max(
|
|
7646
|
+
const dirN = Math.max(1, Math.ceil(numDirEntries * 128 / SS));
|
|
7647
|
+
const miniFatN = Math.ceil(miniSectorList.length / 128);
|
|
7648
|
+
const miniStreamN = Math.ceil(miniStreamData.length / SS);
|
|
7649
|
+
const totalRegStreamN = regNs.reduce((a, b) => a + b, 0);
|
|
7650
|
+
const neededDataSec = dirN + miniFatN + miniStreamN + totalRegStreamN;
|
|
7387
7651
|
let fatN = 1;
|
|
7388
7652
|
for (let iter = 0; iter < 10; iter++) {
|
|
7389
|
-
const
|
|
7390
|
-
const
|
|
7391
|
-
if (
|
|
7392
|
-
fatN =
|
|
7393
|
-
}
|
|
7394
|
-
const
|
|
7395
|
-
const
|
|
7396
|
-
const
|
|
7397
|
-
const
|
|
7398
|
-
|
|
7399
|
-
let
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
}
|
|
7404
|
-
const totalSec = curSec;
|
|
7653
|
+
const totalSec2 = fatN + neededDataSec;
|
|
7654
|
+
const neededFat = Math.ceil(totalSec2 / 128);
|
|
7655
|
+
if (neededFat <= fatN) break;
|
|
7656
|
+
fatN = neededFat;
|
|
7657
|
+
}
|
|
7658
|
+
const totalSec = fatN + neededDataSec;
|
|
7659
|
+
const dirStartSec = fatN;
|
|
7660
|
+
const miniFatStartSec = dirStartSec + dirN;
|
|
7661
|
+
const miniStreamStartSec = miniFatStartSec + miniFatN;
|
|
7662
|
+
let curSec = miniStreamStartSec + miniStreamN;
|
|
7663
|
+
for (let i = 0; i < regularStreams.length; i++) {
|
|
7664
|
+
regularStreams[i].startSec = curSec;
|
|
7665
|
+
curSec += regNs[i];
|
|
7666
|
+
}
|
|
7405
7667
|
const fatBuf = new Uint8Array(fatN * SS).fill(255);
|
|
7406
7668
|
const setFat = (i, v) => {
|
|
7407
|
-
|
|
7408
|
-
fatBuf[
|
|
7409
|
-
fatBuf[
|
|
7410
|
-
fatBuf[
|
|
7669
|
+
const off = i * 4;
|
|
7670
|
+
fatBuf[off] = v & 255;
|
|
7671
|
+
fatBuf[off + 1] = v >>> 8 & 255;
|
|
7672
|
+
fatBuf[off + 2] = v >>> 16 & 255;
|
|
7673
|
+
fatBuf[off + 3] = v >>> 24 & 255;
|
|
7411
7674
|
};
|
|
7412
|
-
for (let i = 0; i < fatN; i++)
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
for (let i = 0; i <
|
|
7416
|
-
setFat(
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7675
|
+
for (let i = 0; i < fatN; i++) {
|
|
7676
|
+
setFat(i, FATSECT);
|
|
7677
|
+
}
|
|
7678
|
+
for (let i = 0; i < dirN; i++) {
|
|
7679
|
+
setFat(
|
|
7680
|
+
dirStartSec + i,
|
|
7681
|
+
i + 1 < dirN ? dirStartSec + i + 1 : ENDOFCHAIN
|
|
7682
|
+
);
|
|
7683
|
+
}
|
|
7684
|
+
if (miniFatN > 0) {
|
|
7685
|
+
for (let i = 0; i < miniFatN; i++) {
|
|
7686
|
+
setFat(
|
|
7687
|
+
miniFatStartSec + i,
|
|
7688
|
+
i + 1 < miniFatN ? miniFatStartSec + i + 1 : ENDOFCHAIN
|
|
7689
|
+
);
|
|
7690
|
+
}
|
|
7691
|
+
}
|
|
7692
|
+
if (miniStreamN > 0) {
|
|
7693
|
+
for (let i = 0; i < miniStreamN; i++) {
|
|
7694
|
+
setFat(
|
|
7695
|
+
miniStreamStartSec + i,
|
|
7696
|
+
i + 1 < miniStreamN ? miniStreamStartSec + i + 1 : ENDOFCHAIN
|
|
7697
|
+
);
|
|
7698
|
+
}
|
|
7699
|
+
}
|
|
7700
|
+
for (let i = 0; i < regularStreams.length; i++) {
|
|
7701
|
+
const s = regularStreams[i];
|
|
7702
|
+
const n = regNs[i];
|
|
7703
|
+
const start = s.startSec;
|
|
7704
|
+
for (let j = 0; j < n; j++) {
|
|
7705
|
+
setFat(start + j, j + 1 < n ? start + j + 1 : ENDOFCHAIN);
|
|
7706
|
+
}
|
|
7707
|
+
}
|
|
7708
|
+
const miniFatBuf = new Uint8Array(miniFatN * SS).fill(255);
|
|
7709
|
+
const setMiniFat = (i, v) => {
|
|
7710
|
+
const off = i * 4;
|
|
7711
|
+
miniFatBuf[off] = v & 255;
|
|
7712
|
+
miniFatBuf[off + 1] = v >>> 8 & 255;
|
|
7713
|
+
miniFatBuf[off + 2] = v >>> 16 & 255;
|
|
7714
|
+
miniFatBuf[off + 3] = v >>> 24 & 255;
|
|
7715
|
+
};
|
|
7716
|
+
for (let i = 0; i < miniSectorList.length; i++) {
|
|
7717
|
+
setMiniFat(i, miniSectorList[i]);
|
|
7426
7718
|
}
|
|
7427
7719
|
const dirBuf = new Uint8Array(dirN * SS);
|
|
7428
7720
|
const dv = new DataView(dirBuf.buffer);
|
|
7429
7721
|
function writeDirEntry(idx, name, type, left, right, child, startSec, size) {
|
|
7430
7722
|
const base = idx * 128;
|
|
7431
7723
|
const nl = name.length;
|
|
7432
|
-
for (let i = 0; i < nl; i++)
|
|
7724
|
+
for (let i = 0; i < nl; i++) {
|
|
7433
7725
|
dv.setUint16(base + i * 2, name.charCodeAt(i), true);
|
|
7726
|
+
}
|
|
7434
7727
|
dv.setUint16(base + 64, (nl + 1) * 2, true);
|
|
7435
7728
|
dirBuf[base + 66] = type;
|
|
7436
7729
|
dirBuf[base + 67] = 1;
|
|
@@ -7446,35 +7739,20 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7446
7739
|
dv.setInt32(base + 72, -1, true);
|
|
7447
7740
|
dv.setInt32(base + 76, -1, true);
|
|
7448
7741
|
}
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
writeDirEntry(2, "DocInfo", 2, -1, 3, -1, diSec, docInfoData.length);
|
|
7453
|
-
writeDirEntry(3, "BodyText", 1, -1, 5, 4, ENDOFCHAIN, 0);
|
|
7454
|
-
writeDirEntry(4, "Section0", 2, -1, -1, -1, s0Sec, section0Data.length);
|
|
7455
|
-
writeDirEntry(5, "BinData", 1, -1, -1, 6, ENDOFCHAIN, 0);
|
|
7456
|
-
for (let ii = 0; ii < binImages.length; ii++) {
|
|
7457
|
-
const img = binImages[ii];
|
|
7458
|
-
const streamName = `BIN${String(img.id).padStart(4, "0")}.${img.ext}`;
|
|
7459
|
-
const sibling = ii + 1 < binImages.length ? 7 + ii : -1;
|
|
7460
|
-
writeDirEntry(
|
|
7461
|
-
6 + ii,
|
|
7462
|
-
streamName,
|
|
7463
|
-
2,
|
|
7464
|
-
-1,
|
|
7465
|
-
sibling,
|
|
7466
|
-
-1,
|
|
7467
|
-
imgSecs[ii],
|
|
7468
|
-
img.data.length
|
|
7469
|
-
);
|
|
7470
|
-
}
|
|
7471
|
-
} else {
|
|
7472
|
-
writeDirEntry(0, "Root Entry", 5, -1, -1, 1, ENDOFCHAIN, 0);
|
|
7473
|
-
writeDirEntry(1, "FileHeader", 2, -1, 2, -1, fhSec, fileHeaderData.length);
|
|
7474
|
-
writeDirEntry(2, "DocInfo", 2, -1, 3, -1, diSec, docInfoData.length);
|
|
7475
|
-
writeDirEntry(3, "BodyText", 1, -1, -1, 4, ENDOFCHAIN, 0);
|
|
7476
|
-
writeDirEntry(4, "Section0", 2, -1, -1, -1, s0Sec, section0Data.length);
|
|
7742
|
+
const streamMap = /* @__PURE__ */ new Map();
|
|
7743
|
+
for (const s of streams) {
|
|
7744
|
+
streamMap.set(s.dirIdx, s);
|
|
7477
7745
|
}
|
|
7746
|
+
writeDirEntry(
|
|
7747
|
+
0,
|
|
7748
|
+
"Root Entry",
|
|
7749
|
+
5,
|
|
7750
|
+
-1,
|
|
7751
|
+
-1,
|
|
7752
|
+
3,
|
|
7753
|
+
miniStreamStartSec,
|
|
7754
|
+
miniStreamData.length
|
|
7755
|
+
);
|
|
7478
7756
|
const HWP_CLSID = [
|
|
7479
7757
|
32,
|
|
7480
7758
|
233,
|
|
@@ -7493,7 +7771,61 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7493
7771
|
155,
|
|
7494
7772
|
113
|
|
7495
7773
|
];
|
|
7496
|
-
for (let i = 0; i < 16; i++)
|
|
7774
|
+
for (let i = 0; i < 16; i++) {
|
|
7775
|
+
dirBuf[0 * 128 + 80 + i] = HWP_CLSID[i];
|
|
7776
|
+
}
|
|
7777
|
+
const fhStream = streamMap.get(1);
|
|
7778
|
+
writeDirEntry(
|
|
7779
|
+
1,
|
|
7780
|
+
"FileHeader",
|
|
7781
|
+
2,
|
|
7782
|
+
-1,
|
|
7783
|
+
-1,
|
|
7784
|
+
-1,
|
|
7785
|
+
fhStream.startSec,
|
|
7786
|
+
fhStream.data.length
|
|
7787
|
+
);
|
|
7788
|
+
const diStream = streamMap.get(2);
|
|
7789
|
+
const docInfoLeft = binImages.length > 0 ? 5 : -1;
|
|
7790
|
+
writeDirEntry(
|
|
7791
|
+
2,
|
|
7792
|
+
"DocInfo",
|
|
7793
|
+
2,
|
|
7794
|
+
docInfoLeft,
|
|
7795
|
+
-1,
|
|
7796
|
+
-1,
|
|
7797
|
+
diStream.startSec,
|
|
7798
|
+
diStream.data.length
|
|
7799
|
+
);
|
|
7800
|
+
writeDirEntry(3, "BodyText", 1, 2, 1, 4, ENDOFCHAIN, 0);
|
|
7801
|
+
const s0Stream = streamMap.get(4);
|
|
7802
|
+
writeDirEntry(
|
|
7803
|
+
4,
|
|
7804
|
+
"Section0",
|
|
7805
|
+
2,
|
|
7806
|
+
-1,
|
|
7807
|
+
-1,
|
|
7808
|
+
-1,
|
|
7809
|
+
s0Stream.startSec,
|
|
7810
|
+
s0Stream.data.length
|
|
7811
|
+
);
|
|
7812
|
+
if (binImages.length > 0) {
|
|
7813
|
+
writeDirEntry(5, "BinData", 1, -1, -1, 6, ENDOFCHAIN, 0);
|
|
7814
|
+
for (let i = 0; i < binImages.length; i++) {
|
|
7815
|
+
const imgStream = streamMap.get(6 + i);
|
|
7816
|
+
const sibling = i + 1 < binImages.length ? 7 + i : -1;
|
|
7817
|
+
writeDirEntry(
|
|
7818
|
+
6 + i,
|
|
7819
|
+
imgStream.name,
|
|
7820
|
+
2,
|
|
7821
|
+
-1,
|
|
7822
|
+
sibling,
|
|
7823
|
+
-1,
|
|
7824
|
+
imgStream.startSec,
|
|
7825
|
+
imgStream.data.length
|
|
7826
|
+
);
|
|
7827
|
+
}
|
|
7828
|
+
}
|
|
7497
7829
|
const hdr = new Uint8Array(SS);
|
|
7498
7830
|
const hdv = new DataView(hdr.buffer);
|
|
7499
7831
|
const MAGIC = [208, 207, 17, 224, 161, 177, 26, 225];
|
|
@@ -7502,32 +7834,43 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7502
7834
|
});
|
|
7503
7835
|
hdv.setUint16(24, 62, true);
|
|
7504
7836
|
hdv.setUint16(26, 3, true);
|
|
7505
|
-
hdv.setUint16(28,
|
|
7837
|
+
hdv.setUint16(28, 65534, true);
|
|
7506
7838
|
hdv.setUint16(30, 9, true);
|
|
7507
7839
|
hdv.setUint16(32, 6, true);
|
|
7508
|
-
hdv.setUint32(40,
|
|
7509
|
-
hdv.setUint32(44,
|
|
7510
|
-
hdv.setUint32(48,
|
|
7511
|
-
hdv.setUint32(52,
|
|
7512
|
-
hdv.setUint32(56,
|
|
7513
|
-
hdv.setUint32(60, 0, true);
|
|
7514
|
-
hdv.setUint32(64,
|
|
7515
|
-
hdv.setUint32(68,
|
|
7840
|
+
hdv.setUint32(40, 0, true);
|
|
7841
|
+
hdv.setUint32(44, fatN, true);
|
|
7842
|
+
hdv.setUint32(48, dirStartSec, true);
|
|
7843
|
+
hdv.setUint32(52, 0, true);
|
|
7844
|
+
hdv.setUint32(56, 4096, true);
|
|
7845
|
+
hdv.setUint32(60, miniFatN > 0 ? miniFatStartSec : ENDOFCHAIN, true);
|
|
7846
|
+
hdv.setUint32(64, miniFatN, true);
|
|
7847
|
+
hdv.setUint32(68, ENDOFCHAIN, true);
|
|
7516
7848
|
hdv.setUint32(72, 0, true);
|
|
7517
7849
|
for (let i = 0; i < 109; i++) {
|
|
7518
7850
|
hdv.setUint32(76 + i * 4, i < fatN ? i : FREESECT, true);
|
|
7519
7851
|
}
|
|
7520
7852
|
const out = new Uint8Array(SS + totalSec * SS);
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
out.set(
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7853
|
+
let outOff = 0;
|
|
7854
|
+
out.set(hdr, outOff);
|
|
7855
|
+
outOff += SS;
|
|
7856
|
+
out.set(fatBuf, outOff);
|
|
7857
|
+
outOff += fatN * SS;
|
|
7858
|
+
out.set(dirBuf, outOff);
|
|
7859
|
+
outOff += dirN * SS;
|
|
7860
|
+
if (miniFatN > 0) {
|
|
7861
|
+
out.set(miniFatBuf, outOff);
|
|
7862
|
+
outOff += miniFatN * SS;
|
|
7863
|
+
}
|
|
7864
|
+
if (miniStreamN > 0) {
|
|
7865
|
+
const miniStreamPad = new Uint8Array(miniStreamN * SS);
|
|
7866
|
+
miniStreamPad.set(miniStreamData);
|
|
7867
|
+
out.set(miniStreamPad, outOff);
|
|
7868
|
+
outOff += miniStreamN * SS;
|
|
7869
|
+
}
|
|
7870
|
+
for (let i = 0; i < regularStreams.length; i++) {
|
|
7871
|
+
out.set(regPads[i], outOff);
|
|
7872
|
+
outOff += regNs[i] * SS;
|
|
7873
|
+
}
|
|
7531
7874
|
return out;
|
|
7532
7875
|
}
|
|
7533
7876
|
function concatU8(arrays) {
|