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.js
CHANGED
|
@@ -1423,6 +1423,17 @@ function decodeGrid(tbl, ctx) {
|
|
|
1423
1423
|
const headerRow = tblAttr.repeatHeader === "1";
|
|
1424
1424
|
const gridProps = { headerRow: headerRow || void 0 };
|
|
1425
1425
|
if (borderFill?.stroke) gridProps.defaultStroke = borderFill.stroke;
|
|
1426
|
+
const posAttr = tbl?.["hp:pos"]?.[0]?._attr ?? {};
|
|
1427
|
+
if (posAttr.horzAlign) {
|
|
1428
|
+
const alignMap = {
|
|
1429
|
+
LEFT: "left",
|
|
1430
|
+
RIGHT: "right",
|
|
1431
|
+
CENTER: "center",
|
|
1432
|
+
JUSTIFY: "justify"
|
|
1433
|
+
};
|
|
1434
|
+
const a = alignMap[posAttr.horzAlign];
|
|
1435
|
+
if (a) gridProps.align = a;
|
|
1436
|
+
}
|
|
1426
1437
|
const rowArr = getTag(tbl, "hp:tr", "hp:ROW");
|
|
1427
1438
|
for (const row of rowArr) {
|
|
1428
1439
|
const cells = getTag(row, "hp:tc", "hp:CELL");
|
|
@@ -1505,16 +1516,15 @@ function decodeGrid(tbl, ctx) {
|
|
|
1505
1516
|
};
|
|
1506
1517
|
cellProps.va = vaMap[subAttr.vertAlign];
|
|
1507
1518
|
}
|
|
1508
|
-
const
|
|
1509
|
-
const
|
|
1510
|
-
const
|
|
1511
|
-
const
|
|
1512
|
-
const
|
|
1513
|
-
|
|
1514
|
-
if (
|
|
1515
|
-
if (
|
|
1516
|
-
if (
|
|
1517
|
-
if (mB !== HWPX_DEFAULT_MARGIN_TB) cellProps.padB = Metric.hwpToPt(mB);
|
|
1519
|
+
const cellMarginAttr = cell?.["hp:cellMargin"]?.[0]?._attr ?? {};
|
|
1520
|
+
const mL = cellMarginAttr.left !== void 0 ? Number(cellMarginAttr.left) : -1;
|
|
1521
|
+
const mR = cellMarginAttr.right !== void 0 ? Number(cellMarginAttr.right) : -1;
|
|
1522
|
+
const mT = cellMarginAttr.top !== void 0 ? Number(cellMarginAttr.top) : -1;
|
|
1523
|
+
const mB = cellMarginAttr.bottom !== void 0 ? Number(cellMarginAttr.bottom) : -1;
|
|
1524
|
+
if (mL >= 0) cellProps.padL = Metric.hwpToPt(mL);
|
|
1525
|
+
if (mR >= 0) cellProps.padR = Metric.hwpToPt(mR);
|
|
1526
|
+
if (mT >= 0) cellProps.padT = Metric.hwpToPt(mT);
|
|
1527
|
+
if (mB >= 0) cellProps.padB = Metric.hwpToPt(mB);
|
|
1518
1528
|
const cellSpan = cell?.["hp:cellSpan"]?.[0]?._attr ?? {};
|
|
1519
1529
|
const cs = Number(cellSpan.colSpan ?? ca.ColSpan ?? 1);
|
|
1520
1530
|
const rs = Number(cellSpan.rowSpan ?? ca.RowSpan ?? 1);
|
|
@@ -1774,6 +1784,9 @@ var CTRL_IMAGE = 1768777504;
|
|
|
1774
1784
|
var CTRL_OBJ = 1868720672;
|
|
1775
1785
|
var CTRL_FIG = 1718183712;
|
|
1776
1786
|
var CTRL_GSO = 1735618336;
|
|
1787
|
+
var CTRL_HEAD = 1751474532;
|
|
1788
|
+
var CTRL_FOOT = 1718579060;
|
|
1789
|
+
var CTRL_ATNO = 1635020399;
|
|
1777
1790
|
function parseRecords(data) {
|
|
1778
1791
|
const out = [];
|
|
1779
1792
|
let off = 0;
|
|
@@ -1851,19 +1864,29 @@ function parseCharShape(d) {
|
|
|
1851
1864
|
textColor: d.length >= 56 ? colorRef(d, 52) : "000000"
|
|
1852
1865
|
};
|
|
1853
1866
|
}
|
|
1854
|
-
var ALIGN_TBL = { 0: "justify", 1: "left", 2: "right", 3: "center", 4: "
|
|
1867
|
+
var ALIGN_TBL = { 0: "justify", 1: "left", 2: "right", 3: "center", 4: "distribute", 5: "distribute_space" };
|
|
1855
1868
|
function parseParaShape(d) {
|
|
1856
|
-
if (d.length < 4) return { align: "left", spaceBefore: 0, spaceAfter: 0, lineSpacing: 160, leftMargin: 0, indent: 0 };
|
|
1869
|
+
if (d.length < 4) return { align: "left", spaceBefore: 0, spaceAfter: 0, lineSpacing: 160, lineSpacingType: 0, leftMargin: 0, rightMargin: 0, indent: 0 };
|
|
1857
1870
|
const attr = BinaryKit.readU32LE(d, 0);
|
|
1871
|
+
const lineSpacingType = attr & 3;
|
|
1872
|
+
const align = ALIGN_TBL[attr >> 2 & 7] ?? "left";
|
|
1873
|
+
const vVal = attr >> 18 & 3;
|
|
1874
|
+
const verAlign = vVal === 1 ? "top" : vVal === 2 ? "center" : vVal === 3 ? "bottom" : "baseline";
|
|
1875
|
+
const lineWrap = "break";
|
|
1858
1876
|
return {
|
|
1859
|
-
align
|
|
1877
|
+
align,
|
|
1878
|
+
lineSpacingType,
|
|
1860
1879
|
leftMargin: d.length >= 8 ? i32(d, 4) : 0,
|
|
1861
|
-
// offset 4:
|
|
1880
|
+
// offset 4: 문단 몸체 왼쪽 여백 (HWPUNIT)
|
|
1881
|
+
rightMargin: d.length >= 12 ? i32(d, 8) : 0,
|
|
1882
|
+
// offset 8: 문단 몸체 오른쪽 여백 (HWPUNIT)
|
|
1862
1883
|
indent: d.length >= 16 ? i32(d, 12) : 0,
|
|
1863
|
-
// offset 12:
|
|
1884
|
+
// offset 12: 첫 줄 들여쓰기 (HWPUNIT)
|
|
1864
1885
|
spaceBefore: d.length >= 20 ? i32(d, 16) : 0,
|
|
1865
1886
|
spaceAfter: d.length >= 24 ? i32(d, 20) : 0,
|
|
1866
|
-
lineSpacing: d.length >= 28 ? i32(d, 24) : 160
|
|
1887
|
+
lineSpacing: d.length >= 28 ? i32(d, 24) : 160,
|
|
1888
|
+
verAlign,
|
|
1889
|
+
lineWrap
|
|
1867
1890
|
};
|
|
1868
1891
|
}
|
|
1869
1892
|
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];
|
|
@@ -1919,6 +1942,8 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1919
1942
|
const hdr = recs[start];
|
|
1920
1943
|
const lv = hdr.level;
|
|
1921
1944
|
const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;
|
|
1945
|
+
const hwpStyleId = hdr.data.length >= 11 ? hdr.data[10] : 0;
|
|
1946
|
+
const divideSort = hdr.data.length >= 12 ? hdr.data[11] : 0;
|
|
1922
1947
|
const ps = di.paraShapes[psId];
|
|
1923
1948
|
let text = null;
|
|
1924
1949
|
let csPairs = [];
|
|
@@ -1936,23 +1961,48 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1936
1961
|
} else if (r.tag === TAG_CTRL_HEADER && r.level === lv + 1) {
|
|
1937
1962
|
if (r.data.length >= 4) {
|
|
1938
1963
|
const ctrlId = BinaryKit.readU32LE(r.data, 0);
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1964
|
+
if (ctrlId === CTRL_HEAD || ctrlId === CTRL_FOOT) {
|
|
1965
|
+
const ctrlLv = r.level;
|
|
1966
|
+
const hfParas = [];
|
|
1967
|
+
let j = i + 1;
|
|
1968
|
+
while (j < recs.length && recs[j].level > ctrlLv) {
|
|
1969
|
+
if (recs[j].tag === TAG_PARA_HEADER) {
|
|
1970
|
+
const pr = shield.guard(
|
|
1971
|
+
() => parseParagraphGroup(recs, j, di, shield, gsoCtx),
|
|
1972
|
+
{ nodes: [], next: j + 1 },
|
|
1973
|
+
`hwp:hf@${j}`
|
|
1974
|
+
);
|
|
1975
|
+
hfParas.push(...pr.nodes.filter((n) => n.tag === "para"));
|
|
1976
|
+
j = pr.next;
|
|
1977
|
+
} else {
|
|
1978
|
+
j++;
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
if (hfParas.length > 0) {
|
|
1982
|
+
const key = ctrlId === CTRL_HEAD ? "headers" : "footers";
|
|
1983
|
+
if (!gsoCtx[key]) gsoCtx[key] = hfParas;
|
|
1984
|
+
}
|
|
1985
|
+
i = j;
|
|
1954
1986
|
} else {
|
|
1955
|
-
|
|
1987
|
+
const MAX_HWP = 1e6;
|
|
1988
|
+
const rawW = r.data.length >= 24 ? BinaryKit.readU32LE(r.data, 16) : 0;
|
|
1989
|
+
const rawH = r.data.length >= 28 ? BinaryKit.readU32LE(r.data, 20) : 0;
|
|
1990
|
+
const wPt = rawW > 0 && rawW < MAX_HWP ? Metric.hwpToPt(rawW) : 0;
|
|
1991
|
+
const hPt = rawH > 0 && rawH < MAX_HWP ? Metric.hwpToPt(rawH) : 0;
|
|
1992
|
+
const atnoType = ctrlId === CTRL_ATNO && r.data.length >= 8 ? BinaryKit.readU32LE(r.data, 4) & 15 : void 0;
|
|
1993
|
+
const imgId = ctrlId === CTRL_GSO ? gsoCtx.count++ : r.data.length >= 6 ? BinaryKit.readU16LE(r.data, 4) : 0;
|
|
1994
|
+
ctrlHeaders.push({ ctrlId, imgId, wPt, hPt, atnoType });
|
|
1995
|
+
if (ctrlId === CTRL_TABLE) {
|
|
1996
|
+
const tr = shield.guard(
|
|
1997
|
+
() => parseTableCtrl(recs, i, di, shield, gsoCtx),
|
|
1998
|
+
{ grid: null, next: skipKids(recs, i) },
|
|
1999
|
+
`hwp:tbl@${i}`
|
|
2000
|
+
);
|
|
2001
|
+
if (tr.grid) grids.push(tr.grid);
|
|
2002
|
+
i = tr.next;
|
|
2003
|
+
} else {
|
|
2004
|
+
i = skipKids(recs, i);
|
|
2005
|
+
}
|
|
1956
2006
|
}
|
|
1957
2007
|
} else {
|
|
1958
2008
|
i = skipKids(recs, i);
|
|
@@ -1962,13 +2012,35 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1962
2012
|
}
|
|
1963
2013
|
}
|
|
1964
2014
|
const nodes = [];
|
|
1965
|
-
|
|
2015
|
+
{
|
|
1966
2016
|
const paraContent = [];
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
2017
|
+
const atnoCtrls = [];
|
|
2018
|
+
if (text && text.controls.length > 0) {
|
|
2019
|
+
for (let ci = 0; ci < text.controls.length; ci++) {
|
|
2020
|
+
const ch = ctrlHeaders[ci];
|
|
2021
|
+
if (ch && ch.ctrlId === CTRL_ATNO)
|
|
2022
|
+
atnoCtrls.push({ pos: text.controls[ci].pos, type: ch.atnoType ?? 0 });
|
|
2023
|
+
}
|
|
2024
|
+
atnoCtrls.sort((a, b) => a.pos - b.pos);
|
|
2025
|
+
}
|
|
2026
|
+
if (text && text.chars.length > 0) {
|
|
2027
|
+
if (atnoCtrls.length > 0) {
|
|
2028
|
+
let k = 0;
|
|
2029
|
+
for (const ac of atnoCtrls) {
|
|
2030
|
+
const seg = [];
|
|
2031
|
+
while (k < text.chars.length && text.chars[k].pos < ac.pos) seg.push(text.chars[k++]);
|
|
2032
|
+
if (seg.length > 0) paraContent.push(...resolveCharShapes(seg, csPairs, di));
|
|
2033
|
+
paraContent.push(buildPageNum(ac.type === 0 ? "decimal" : "total"));
|
|
2034
|
+
}
|
|
2035
|
+
const rest = text.chars.slice(k);
|
|
2036
|
+
if (rest.length > 0) paraContent.push(...resolveCharShapes(rest, csPairs, di));
|
|
2037
|
+
} else {
|
|
2038
|
+
paraContent.push(...resolveCharShapes(text.chars, csPairs, di));
|
|
2039
|
+
}
|
|
2040
|
+
} else if (atnoCtrls.length > 0) {
|
|
2041
|
+
for (const ac of atnoCtrls) paraContent.push(buildPageNum(ac.type === 0 ? "decimal" : "total"));
|
|
1970
2042
|
}
|
|
1971
|
-
if (text.controls.length > 0) {
|
|
2043
|
+
if (text && text.controls.length > 0) {
|
|
1972
2044
|
for (let ci = 0; ci < text.controls.length; ci++) {
|
|
1973
2045
|
const ch = ctrlHeaders[ci];
|
|
1974
2046
|
if (!ch) continue;
|
|
@@ -1978,11 +2050,15 @@ function parseParagraphGroup(recs, start, di, shield, gsoCtx) {
|
|
|
1978
2050
|
paraContent.push(buildSpan(`__EXT_${ch.imgId}${dimStr}__`));
|
|
1979
2051
|
}
|
|
1980
2052
|
}
|
|
1981
|
-
if (
|
|
1982
|
-
nodes.push(buildPara(
|
|
2053
|
+
if (divideSort & 4) {
|
|
2054
|
+
nodes.push(buildPara([{ tag: "span", props: {}, kids: [buildPb()] }]));
|
|
1983
2055
|
}
|
|
2056
|
+
nodes.push(...grids);
|
|
2057
|
+
nodes.push(buildPara(
|
|
2058
|
+
paraContent.length > 0 ? paraContent : [buildSpan("")],
|
|
2059
|
+
buildParaProps(ps, hwpStyleId)
|
|
2060
|
+
));
|
|
1984
2061
|
}
|
|
1985
|
-
nodes.push(...grids);
|
|
1986
2062
|
return { nodes, next: i };
|
|
1987
2063
|
}
|
|
1988
2064
|
function skipKids(recs, idx) {
|
|
@@ -1991,7 +2067,7 @@ function skipKids(recs, idx) {
|
|
|
1991
2067
|
while (i < recs.length && recs[i].level > lv) i++;
|
|
1992
2068
|
return i;
|
|
1993
2069
|
}
|
|
1994
|
-
var EXT_CTRL = /* @__PURE__ */ new Set([2, 3, 11, 12, 14, 15]);
|
|
2070
|
+
var EXT_CTRL = /* @__PURE__ */ new Set([2, 3, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]);
|
|
1995
2071
|
var INL_CTRL = /* @__PURE__ */ new Set([4, 5, 6, 7, 8]);
|
|
1996
2072
|
function decodeParaText(d) {
|
|
1997
2073
|
const chars = [];
|
|
@@ -2289,6 +2365,8 @@ function parseCellRec(d, tag, recs, cStart, cEnd, di, shield, seqIdx, colCnt, gs
|
|
|
2289
2365
|
const hdr = recs[k];
|
|
2290
2366
|
const lv = hdr.level;
|
|
2291
2367
|
const psId = hdr.data.length >= 10 ? BinaryKit.readU16LE(hdr.data, 8) : 0;
|
|
2368
|
+
const cellStyleId = hdr.data.length >= 11 ? hdr.data[10] : 0;
|
|
2369
|
+
const cellDivide = hdr.data.length >= 12 ? hdr.data[11] : 0;
|
|
2292
2370
|
const ps = di.paraShapes[psId];
|
|
2293
2371
|
let txt = null;
|
|
2294
2372
|
let csp = [];
|
|
@@ -2340,7 +2418,8 @@ function parseCellRec(d, tag, recs, cStart, cEnd, di, shield, seqIdx, colCnt, gs
|
|
|
2340
2418
|
}
|
|
2341
2419
|
}
|
|
2342
2420
|
const kids = paraContent.length > 0 ? paraContent : [buildSpan("")];
|
|
2343
|
-
const items = [buildPara(kids, buildParaProps(ps))
|
|
2421
|
+
const items = [...innerGrids, buildPara(kids, buildParaProps(ps, cellStyleId))];
|
|
2422
|
+
if (cellDivide & 4) items.unshift(buildPara([{ tag: "span", props: {}, kids: [buildPb()] }]));
|
|
2344
2423
|
return { items, next: j };
|
|
2345
2424
|
},
|
|
2346
2425
|
{ items: [buildPara([buildSpan("")])], next: k + 1 },
|
|
@@ -2393,6 +2472,8 @@ function parsePageDef(d) {
|
|
|
2393
2472
|
const mr = BinaryKit.readU32LE(d, 12);
|
|
2394
2473
|
const mt = BinaryKit.readU32LE(d, 16);
|
|
2395
2474
|
const mb = BinaryKit.readU32LE(d, 20);
|
|
2475
|
+
const header = d.length >= 28 ? BinaryKit.readU32LE(d, 24) : 0;
|
|
2476
|
+
const footer = d.length >= 32 ? BinaryKit.readU32LE(d, 28) : 0;
|
|
2396
2477
|
const at = d.length >= 40 ? BinaryKit.readU32LE(d, 36) : 0;
|
|
2397
2478
|
return {
|
|
2398
2479
|
wPt: Metric.hwpToPt(w),
|
|
@@ -2401,6 +2482,8 @@ function parsePageDef(d) {
|
|
|
2401
2482
|
mr: Metric.hwpToPt(mr),
|
|
2402
2483
|
mt: Metric.hwpToPt(mt),
|
|
2403
2484
|
mb: Metric.hwpToPt(mb),
|
|
2485
|
+
headerPt: header > 0 ? Metric.hwpToPt(header) : void 0,
|
|
2486
|
+
footerPt: footer > 0 ? Metric.hwpToPt(footer) : void 0,
|
|
2404
2487
|
orient: at & 1 ? "landscape" : "portrait"
|
|
2405
2488
|
};
|
|
2406
2489
|
}
|
|
@@ -2431,16 +2514,24 @@ function strokeFromBF(bfId, di) {
|
|
|
2431
2514
|
const b = bf.borders[0];
|
|
2432
2515
|
return { kind: BORDER_KIND[b.type] ?? "solid", pt: b.widthPt, color: b.color };
|
|
2433
2516
|
}
|
|
2434
|
-
function buildParaProps(ps) {
|
|
2435
|
-
|
|
2436
|
-
|
|
2517
|
+
function buildParaProps(ps, hwpStyleId) {
|
|
2518
|
+
const p = hwpStyleId !== void 0 ? { hwpStyleId } : {};
|
|
2519
|
+
if (!ps) return p;
|
|
2437
2520
|
if (ps.align && ps.align !== "left") p.align = ps.align;
|
|
2438
2521
|
if (ps.spaceBefore > 0) p.spaceBefore = Metric.hwpToPt(ps.spaceBefore);
|
|
2439
2522
|
if (ps.spaceAfter > 0) p.spaceAfter = Metric.hwpToPt(ps.spaceAfter);
|
|
2440
|
-
if (ps.
|
|
2523
|
+
if (ps.lineSpacingType === 1) {
|
|
2524
|
+
if (ps.lineSpacing > 0) p.lineHeightFixed = Metric.hwpToPt(ps.lineSpacing);
|
|
2525
|
+
} else {
|
|
2526
|
+
if (ps.lineSpacing > 0) p.lineHeight = ps.lineSpacing / 100;
|
|
2527
|
+
}
|
|
2441
2528
|
const leftMarginPt = Math.max(0, Metric.hwpToPt(ps.leftMargin));
|
|
2442
2529
|
if (leftMarginPt > 0) p.leftMargin = leftMarginPt;
|
|
2530
|
+
const rightMarginPt = Math.max(0, Metric.hwpToPt(ps.rightMargin));
|
|
2531
|
+
if (rightMarginPt > 0) p.indentRightPt = rightMarginPt;
|
|
2443
2532
|
if (ps.indent !== 0) p.firstLineIndentPt = Metric.hwpToPt(ps.indent);
|
|
2533
|
+
if (ps.verAlign && ps.verAlign !== "baseline") p.verAlign = ps.verAlign;
|
|
2534
|
+
if (ps.lineWrap && ps.lineWrap !== "break") p.lineWrap = ps.lineWrap;
|
|
2444
2535
|
return p;
|
|
2445
2536
|
}
|
|
2446
2537
|
var HwpScanner = class {
|
|
@@ -2508,7 +2599,10 @@ var HwpScanner = class {
|
|
|
2508
2599
|
}
|
|
2509
2600
|
warns.push(...shield.flush());
|
|
2510
2601
|
const content = allContent.length > 0 ? allContent : [buildPara([buildSpan("")])];
|
|
2511
|
-
return succeed(buildRoot({}, [buildSheet(content, pageDims
|
|
2602
|
+
return succeed(buildRoot({}, [buildSheet(content, pageDims, {
|
|
2603
|
+
headers: gsoCtx.headers ? { default: gsoCtx.headers } : void 0,
|
|
2604
|
+
footers: gsoCtx.footers ? { default: gsoCtx.footers } : void 0
|
|
2605
|
+
})]), warns);
|
|
2512
2606
|
} catch (e) {
|
|
2513
2607
|
warns.push(...shield.flush());
|
|
2514
2608
|
return fail(`HWP decode error: ${e?.message ?? String(e)}`, warns);
|
|
@@ -4479,6 +4573,27 @@ var KIND_MAP = {
|
|
|
4479
4573
|
dash_dot: "DASH_DOT",
|
|
4480
4574
|
dash_dot_dot: "DASH_DOT_DOT"
|
|
4481
4575
|
};
|
|
4576
|
+
function quantizeBorderWidth(pt) {
|
|
4577
|
+
const mm = pt * 0.3528;
|
|
4578
|
+
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];
|
|
4579
|
+
let closest = standardWidths[0];
|
|
4580
|
+
let minDiff = Math.abs(mm - closest);
|
|
4581
|
+
for (let i = 1; i < standardWidths.length; i++) {
|
|
4582
|
+
const diff = Math.abs(mm - standardWidths[i]);
|
|
4583
|
+
if (diff < minDiff) {
|
|
4584
|
+
minDiff = diff;
|
|
4585
|
+
closest = standardWidths[i];
|
|
4586
|
+
}
|
|
4587
|
+
}
|
|
4588
|
+
let str = closest.toFixed(2);
|
|
4589
|
+
if (str.endsWith("0")) {
|
|
4590
|
+
str = str.slice(0, -1);
|
|
4591
|
+
}
|
|
4592
|
+
if (str.endsWith(".0")) {
|
|
4593
|
+
str = str.slice(0, -2);
|
|
4594
|
+
}
|
|
4595
|
+
return `${str} mm`;
|
|
4596
|
+
}
|
|
4482
4597
|
var BorderFillBank = class {
|
|
4483
4598
|
constructor() {
|
|
4484
4599
|
this.fills = [];
|
|
@@ -4491,7 +4606,7 @@ var BorderFillBank = class {
|
|
|
4491
4606
|
}
|
|
4492
4607
|
_strokeXml(tag, s) {
|
|
4493
4608
|
const type = s && s.kind !== "none" ? KIND_MAP[s.kind] ?? "SOLID" : "NONE";
|
|
4494
|
-
const w = s && s.kind !== "none" ?
|
|
4609
|
+
const w = s && s.kind !== "none" ? quantizeBorderWidth(s.pt) : "0.12 mm";
|
|
4495
4610
|
const c = s ? s.color.startsWith("#") ? s.color : `#${s.color}` : "#000000";
|
|
4496
4611
|
return `<hh:${tag} type="${type}" width="${w}" color="${c}"/>`;
|
|
4497
4612
|
}
|
|
@@ -4568,7 +4683,7 @@ function charPrKey(p) {
|
|
|
4568
4683
|
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 ?? ""}`;
|
|
4569
4684
|
}
|
|
4570
4685
|
function paraPrKey(p) {
|
|
4571
|
-
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 ?? ""}`;
|
|
4686
|
+
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 ?? ""}`;
|
|
4572
4687
|
}
|
|
4573
4688
|
function registerCharPr(props, ctx) {
|
|
4574
4689
|
const key = charPrKey(props);
|
|
@@ -4592,20 +4707,45 @@ function registerCharPr(props, ctx) {
|
|
|
4592
4707
|
ctx.charPrMap.set(key, id);
|
|
4593
4708
|
return id;
|
|
4594
4709
|
}
|
|
4710
|
+
var ALIGN_MAP2 = {
|
|
4711
|
+
left: "LEFT",
|
|
4712
|
+
center: "CENTER",
|
|
4713
|
+
right: "RIGHT",
|
|
4714
|
+
justify: "JUSTIFY",
|
|
4715
|
+
distribute: "DISTRIBUTE",
|
|
4716
|
+
distribute_space: "DISTRIBUTE_SPACE"
|
|
4717
|
+
};
|
|
4718
|
+
var V_ALIGN_MAP = {
|
|
4719
|
+
baseline: "BASELINE",
|
|
4720
|
+
top: "TOP",
|
|
4721
|
+
center: "CENTER",
|
|
4722
|
+
bottom: "BOTTOM"
|
|
4723
|
+
};
|
|
4724
|
+
var LINE_WRAP_MAP = {
|
|
4725
|
+
break: "BREAK",
|
|
4726
|
+
squeeze: "SQUEEZE",
|
|
4727
|
+
keep: "KEEP"
|
|
4728
|
+
};
|
|
4595
4729
|
function registerParaPr(props, ctx) {
|
|
4596
4730
|
const key = paraPrKey(props);
|
|
4597
4731
|
const existing = ctx.paraPrMap.get(key);
|
|
4598
4732
|
if (existing !== void 0) return existing;
|
|
4599
4733
|
const id = ctx.paraPrs.length;
|
|
4734
|
+
const alignStr = props.align ? ALIGN_MAP2[props.align] ?? "LEFT" : "LEFT";
|
|
4735
|
+
const verAlignStr = props.verAlign ? V_ALIGN_MAP[props.verAlign] ?? "BASELINE" : "BASELINE";
|
|
4736
|
+
const lineWrapStr = props.lineWrap ? LINE_WRAP_MAP[props.lineWrap] ?? "BREAK" : "BREAK";
|
|
4600
4737
|
const def = {
|
|
4601
4738
|
id,
|
|
4602
|
-
align:
|
|
4603
|
-
|
|
4739
|
+
align: alignStr,
|
|
4740
|
+
verAlign: verAlignStr,
|
|
4741
|
+
lineWrap: lineWrapStr,
|
|
4742
|
+
leftHwp: Metric.ptToHwp(props.leftMargin ?? 0),
|
|
4604
4743
|
rightHwp: Metric.ptToHwp(props.indentRightPt ?? 0),
|
|
4605
4744
|
intentHwp: Metric.ptToHwp(props.firstLineIndentPt ?? 0),
|
|
4606
4745
|
prevHwp: Metric.ptToHwp(props.spaceBefore ?? 0),
|
|
4607
4746
|
nextHwp: Metric.ptToHwp(props.spaceAfter ?? 0),
|
|
4608
|
-
lineSpacing: props.lineHeight ? Math.round(props.lineHeight * 100) : 160
|
|
4747
|
+
lineSpacing: props.lineHeightFixed ? 0 : props.lineHeight ? Math.round(props.lineHeight * 100) : 160,
|
|
4748
|
+
lineSpacingFixed: props.lineHeightFixed ? Metric.ptToHwp(props.lineHeightFixed) : void 0
|
|
4609
4749
|
};
|
|
4610
4750
|
if (props.listOrd !== void 0) {
|
|
4611
4751
|
def.listType = props.listOrd ? "DIGIT" : "BULLET";
|
|
@@ -4710,8 +4850,8 @@ var HwpxEncoder = class extends BaseEncoder {
|
|
|
4710
4850
|
try {
|
|
4711
4851
|
const sheet = doc.kids[0];
|
|
4712
4852
|
const dims = normalizeDims(sheet?.dims ?? A4);
|
|
4713
|
-
const safeML = dims.ml
|
|
4714
|
-
const safeMR = dims.mr
|
|
4853
|
+
const safeML = dims.ml !== void 0 && dims.ml >= 0 ? dims.ml : 70.87;
|
|
4854
|
+
const safeMR = dims.mr !== void 0 && dims.mr >= 0 ? dims.mr : 70.87;
|
|
4715
4855
|
const availableWidth = Math.round(
|
|
4716
4856
|
Metric.ptToHwp(dims.wPt) - Metric.ptToHwp(safeML) - Metric.ptToHwp(safeMR)
|
|
4717
4857
|
);
|
|
@@ -4767,9 +4907,9 @@ var HwpxEncoder = class extends BaseEncoder {
|
|
|
4767
4907
|
mime: "application/xml"
|
|
4768
4908
|
},
|
|
4769
4909
|
{
|
|
4770
|
-
name: "META-INF/
|
|
4771
|
-
data: this.stringToBytes(
|
|
4772
|
-
mime: "application/
|
|
4910
|
+
name: "META-INF/manifest.xml",
|
|
4911
|
+
data: this.stringToBytes(MANIFEST_XML),
|
|
4912
|
+
mime: "application/xml"
|
|
4773
4913
|
},
|
|
4774
4914
|
{
|
|
4775
4915
|
name: "Contents/content.hpf",
|
|
@@ -4808,9 +4948,9 @@ var HwpxEncoder = class extends BaseEncoder {
|
|
|
4808
4948
|
}
|
|
4809
4949
|
}
|
|
4810
4950
|
};
|
|
4811
|
-
var VERSION_XML = `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><hv:HCFVersion xmlns:hv="http://www.
|
|
4812
|
-
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"
|
|
4813
|
-
var
|
|
4951
|
+
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"/>`;
|
|
4952
|
+
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>`;
|
|
4953
|
+
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"/>`;
|
|
4814
4954
|
function buildContentHpf(ctx, meta) {
|
|
4815
4955
|
const title = esc(meta?.title ?? "");
|
|
4816
4956
|
const creator = esc(meta?.author ?? "text");
|
|
@@ -4836,6 +4976,18 @@ function buildNumberingsXml() {
|
|
|
4836
4976
|
function buildBulletsXml() {
|
|
4837
4977
|
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>`;
|
|
4838
4978
|
}
|
|
4979
|
+
function buildHeaderSecPrListXml(dims) {
|
|
4980
|
+
const wHwp = Metric.ptToHwp(dims.wPt);
|
|
4981
|
+
const hHwp = Metric.ptToHwp(dims.hPt);
|
|
4982
|
+
const ml = Metric.ptToHwp(dims.ml);
|
|
4983
|
+
const mr = Metric.ptToHwp(dims.mr);
|
|
4984
|
+
const mt = Metric.ptToHwp(dims.mt);
|
|
4985
|
+
const mb = Metric.ptToHwp(dims.mb);
|
|
4986
|
+
const headerZone = dims.headerPt !== void 0 && dims.headerPt > 0 ? Metric.ptToHwp(dims.headerPt) : 0;
|
|
4987
|
+
const footerZone = dims.footerPt !== void 0 && dims.footerPt > 0 ? Metric.ptToHwp(dims.footerPt) : 0;
|
|
4988
|
+
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>`;
|
|
4989
|
+
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>`;
|
|
4990
|
+
}
|
|
4839
4991
|
function buildHeaderXml(dims, meta, ctx) {
|
|
4840
4992
|
const fontFacesXml = ctx.fontBank.toXml();
|
|
4841
4993
|
let charPrXml = "";
|
|
@@ -4849,51 +5001,17 @@ function buildHeaderXml(dims, meta, ctx) {
|
|
|
4849
5001
|
}
|
|
4850
5002
|
let paraPrXml = "";
|
|
4851
5003
|
for (const pp of ctx.paraPrs) {
|
|
4852
|
-
|
|
5004
|
+
const ver = pp.verAlign ?? "BASELINE";
|
|
5005
|
+
const wrap = pp.lineWrap ?? "BREAK";
|
|
5006
|
+
const lsType = pp.lineSpacingFixed !== void 0 ? "FIXED" : "PERCENT";
|
|
5007
|
+
const lsValue = pp.lineSpacingFixed !== void 0 ? pp.lineSpacingFixed : pp.lineSpacing;
|
|
5008
|
+
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>`;
|
|
4853
5009
|
}
|
|
4854
5010
|
const borderFillXml = ctx.borderFillBank.toXml();
|
|
4855
5011
|
const stylesXml2 = `<hh:styles itemCnt="${ctx.hwpxStyles.length}">` + ctx.hwpxStyles.map(
|
|
4856
5012
|
(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"/>`
|
|
4857
5013
|
).join("") + `</hh:styles>`;
|
|
4858
|
-
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
|
|
4859
|
-
<hh:layoutCompatibility>
|
|
4860
|
-
<hh:applyFontWeightToBold />
|
|
4861
|
-
<hh:useInnerUnderline />
|
|
4862
|
-
<hh:useLowercaseStrikeout />
|
|
4863
|
-
<hh:extendLineheightToOffset />
|
|
4864
|
-
<hh:treatQuotationAsLatin />
|
|
4865
|
-
<hh:doNotAlignWhitespaceOnRight />
|
|
4866
|
-
<hh:doNotAdjustWordInJustify />
|
|
4867
|
-
<hh:baseCharUnitOnEAsian />
|
|
4868
|
-
<hh:baseCharUnitOfIndentOnFirstChar />
|
|
4869
|
-
<hh:adjustLineheightToFont />
|
|
4870
|
-
<hh:adjustBaselineInFixedLinespacing />
|
|
4871
|
-
<hh:applyPrevspacingBeneathObject />
|
|
4872
|
-
<hh:applyNextspacingOfLastPara />
|
|
4873
|
-
<hh:adjustParaBorderfillToSpacing />
|
|
4874
|
-
<hh:connectParaBorderfillOfEqualBorder />
|
|
4875
|
-
<hh:adjustParaBorderOffsetWithBorder />
|
|
4876
|
-
<hh:extendLineheightToParaBorderOffset />
|
|
4877
|
-
<hh:applyParaBorderToOutside />
|
|
4878
|
-
<hh:applyMinColumnWidthTo1mm />
|
|
4879
|
-
<hh:applyTabPosBasedOnSegment />
|
|
4880
|
-
<hh:breakTabOverLine />
|
|
4881
|
-
<hh:adjustVertPosOfLine />
|
|
4882
|
-
<hh:doNotAlignLastForbidden />
|
|
4883
|
-
<hh:adjustMarginFromAdjustLineheight />
|
|
4884
|
-
<hh:baseLineSpacingOnLineGrid />
|
|
4885
|
-
<hh:applyCharSpacingToCharGrid />
|
|
4886
|
-
<hh:doNotApplyGridInHeaderFooter />
|
|
4887
|
-
<hh:applyExtendHeaderFooterEachSection />
|
|
4888
|
-
<hh:doNotApplyLinegridAtNoLinespacing />
|
|
4889
|
-
<hh:doNotAdjustEmptyAnchorLine />
|
|
4890
|
-
<hh:overlapBothAllowOverlap />
|
|
4891
|
-
<hh:extendVertLimitToPageMargins />
|
|
4892
|
-
<hh:doNotHoldAnchorOfTable />
|
|
4893
|
-
<hh:doNotFormattingAtBeneathAnchor />
|
|
4894
|
-
<hh:adjustBaselineOfObjectToBottom />
|
|
4895
|
-
</hh:layoutCompatibility>
|
|
4896
|
-
</hh:compatibleDocument><hh:docOption><hh:linkinfo path="" pageInherit="0" footnoteInherit="0"/></hh:docOption><hh:trackchageConfig flags="56"/></hh:head>`;
|
|
5014
|
+
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>`;
|
|
4897
5015
|
}
|
|
4898
5016
|
function buildHeaderFooterRunXml(sheet, dims, ctx) {
|
|
4899
5017
|
const headers = sheet.headers || {};
|
|
@@ -4903,12 +5021,13 @@ function buildHeaderFooterRunXml(sheet, dims, ctx) {
|
|
|
4903
5021
|
const availW = ctx.availableWidth;
|
|
4904
5022
|
const mtHwp = Metric.ptToHwp(dims.mt);
|
|
4905
5023
|
const mbHwp = Metric.ptToHwp(dims.mb);
|
|
4906
|
-
const headerZoneH = dims.headerPt ?
|
|
4907
|
-
const footerZoneH = dims.footerPt ?
|
|
5024
|
+
const headerZoneH = dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 4252;
|
|
5025
|
+
const footerZoneH = dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 4252;
|
|
4908
5026
|
let inner = "";
|
|
4909
5027
|
const hideFirst = !!(headers.first || footers.first);
|
|
4910
5028
|
inner += `<hp:ctrl><hp:pageHiding hideHeader="${hideFirst ? 1 : 0}" hideFooter="${hideFirst ? 1 : 0}" hideMasterPage="0" hideBorder="0" hideFill="0" hidePageNum="0"/></hp:ctrl>`;
|
|
4911
5029
|
for (const [type, paras] of Object.entries(headers)) {
|
|
5030
|
+
if (!Array.isArray(paras) || paras.length === 0) continue;
|
|
4912
5031
|
const applyPageType = type === "even" ? "EVEN" : type === "default" || type === "first" ? "BOTH" : "ODD";
|
|
4913
5032
|
const savedId = ctx.nextElementId;
|
|
4914
5033
|
ctx.nextElementId = 0;
|
|
@@ -4917,6 +5036,7 @@ function buildHeaderFooterRunXml(sheet, dims, ctx) {
|
|
|
4917
5036
|
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>`;
|
|
4918
5037
|
}
|
|
4919
5038
|
for (const [type, paras] of Object.entries(footers)) {
|
|
5039
|
+
if (!Array.isArray(paras) || paras.length === 0) continue;
|
|
4920
5040
|
const applyPageType = type === "even" ? "EVEN" : type === "default" || type === "first" ? "BOTH" : "ODD";
|
|
4921
5041
|
const savedId = ctx.nextElementId;
|
|
4922
5042
|
ctx.nextElementId = 0;
|
|
@@ -4940,10 +5060,10 @@ function buildSectionXml(sheet, dims, ctx) {
|
|
|
4940
5060
|
for (let i = 0; i < kids.length; i++) {
|
|
4941
5061
|
const kid = kids[i];
|
|
4942
5062
|
const isFirst = i === 0;
|
|
4943
|
-
const curSecPr =
|
|
5063
|
+
const curSecPr = "";
|
|
4944
5064
|
const curHfRun = isFirst ? hfRunXml : "";
|
|
4945
5065
|
if (kid.tag === "para") {
|
|
4946
|
-
const { xml, nextVertPos } = encodeParaPositioned(
|
|
5066
|
+
const { xml, nextVertPos, hasPageBreak } = encodeParaPositioned(
|
|
4947
5067
|
kid,
|
|
4948
5068
|
ctx,
|
|
4949
5069
|
vertPos,
|
|
@@ -4954,7 +5074,7 @@ function buildSectionXml(sheet, dims, ctx) {
|
|
|
4954
5074
|
contentXml += xml;
|
|
4955
5075
|
vertPos = nextVertPos;
|
|
4956
5076
|
} else if (kid.tag === "grid") {
|
|
4957
|
-
const { xml, nextVertPos } = encodeGridPositioned(
|
|
5077
|
+
const { xml, nextVertPos, hasPageBreak } = encodeGridPositioned(
|
|
4958
5078
|
kid,
|
|
4959
5079
|
ctx,
|
|
4960
5080
|
vertPos,
|
|
@@ -4969,9 +5089,9 @@ function buildSectionXml(sheet, dims, ctx) {
|
|
|
4969
5089
|
const fs = 1e3;
|
|
4970
5090
|
const vs = 1600;
|
|
4971
5091
|
const { xml: linesegXml } = buildLinesegarray(" ", 0, fs, vs / (fs / 100), availWidth);
|
|
4972
|
-
contentXml = `<hp:p id="${ctx.nextElementId++}" paraPrIDRef="0" styleIDRef="0" pageBreak="0" columnBreak="0" merged="0" paraTcId="0">` +
|
|
5092
|
+
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>`;
|
|
4973
5093
|
}
|
|
4974
|
-
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>`;
|
|
5094
|
+
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>`;
|
|
4975
5095
|
}
|
|
4976
5096
|
function buildSecPrXml(dims) {
|
|
4977
5097
|
const wHwp = Metric.ptToHwp(dims.wPt);
|
|
@@ -4980,24 +5100,62 @@ function buildSecPrXml(dims) {
|
|
|
4980
5100
|
const mr = Metric.ptToHwp(dims.mr);
|
|
4981
5101
|
const mt = Metric.ptToHwp(dims.mt);
|
|
4982
5102
|
const mb = Metric.ptToHwp(dims.mb);
|
|
4983
|
-
const headerZone = dims.headerPt ?
|
|
4984
|
-
const footerZone = dims.footerPt ?
|
|
5103
|
+
const headerZone = dims.headerPt ? Metric.ptToHwp(dims.headerPt) : 0;
|
|
5104
|
+
const footerZone = dims.footerPt ? Metric.ptToHwp(dims.footerPt) : 0;
|
|
4985
5105
|
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>`;
|
|
4986
|
-
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="
|
|
5106
|
+
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>`;
|
|
4987
5107
|
}
|
|
4988
5108
|
function buildLinesegarray(text, vertPosStart, fontSize, lineSpacingPct, horzSize) {
|
|
4989
5109
|
const vertsizeLine = Math.round(fontSize * lineSpacingPct / 100);
|
|
4990
5110
|
const spacing = vertsizeLine - fontSize;
|
|
4991
5111
|
const baseline = Math.round(fontSize * 0.83);
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
5112
|
+
if (text.length === 0) {
|
|
5113
|
+
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>`;
|
|
5114
|
+
return { xml, totalHeight: vertsizeLine };
|
|
5115
|
+
}
|
|
5116
|
+
const lines = [];
|
|
5117
|
+
let currentLineWidth = 0;
|
|
5118
|
+
let lineStartIdx = 0;
|
|
5119
|
+
for (let i = 0; i < text.length; i++) {
|
|
5120
|
+
const charCode = text.charCodeAt(i);
|
|
5121
|
+
if (charCode === 10 || charCode === 13) {
|
|
5122
|
+
lines.push({ startPos: lineStartIdx, width: currentLineWidth });
|
|
5123
|
+
lineStartIdx = i + 1;
|
|
5124
|
+
currentLineWidth = 0;
|
|
5125
|
+
continue;
|
|
5126
|
+
}
|
|
5127
|
+
let charW = fontSize * 0.55;
|
|
5128
|
+
if (charCode >= 44032 && charCode <= 55203) {
|
|
5129
|
+
charW = fontSize;
|
|
5130
|
+
} else if (charCode >= 12592 && charCode <= 12687) {
|
|
5131
|
+
charW = fontSize;
|
|
5132
|
+
} else if (charCode >= 19968 && charCode <= 40959) {
|
|
5133
|
+
charW = fontSize;
|
|
5134
|
+
} else if (charCode >= 65 && charCode <= 90) {
|
|
5135
|
+
charW = fontSize * 0.65;
|
|
5136
|
+
} else if (charCode === 32) {
|
|
5137
|
+
charW = fontSize * 0.32;
|
|
5138
|
+
} else if (charCode > 255) {
|
|
5139
|
+
charW = fontSize;
|
|
5140
|
+
} else {
|
|
5141
|
+
charW = fontSize * 0.42;
|
|
5142
|
+
}
|
|
5143
|
+
if (currentLineWidth + charW > horzSize && i > lineStartIdx) {
|
|
5144
|
+
lines.push({ startPos: lineStartIdx, width: currentLineWidth });
|
|
5145
|
+
lineStartIdx = i;
|
|
5146
|
+
currentLineWidth = charW;
|
|
5147
|
+
} else {
|
|
5148
|
+
currentLineWidth += charW;
|
|
5149
|
+
}
|
|
5150
|
+
}
|
|
5151
|
+
lines.push({ startPos: lineStartIdx, width: currentLineWidth });
|
|
5152
|
+
const lineCount = lines.length;
|
|
4996
5153
|
const linesegParts = [];
|
|
4997
5154
|
for (let i = 0; i < lineCount; i++) {
|
|
4998
5155
|
const flags = i === 0 ? LINESEG_FLAGS_FIRST : LINESEG_FLAGS_OTHER;
|
|
5156
|
+
const textpos = lines[i].startPos;
|
|
4999
5157
|
linesegParts.push(
|
|
5000
|
-
`<hp:lineseg textpos="${
|
|
5158
|
+
`<hp:lineseg textpos="${textpos}" vertpos="${vertPosStart + i * vertsizeLine}" vertsize="${vertsizeLine}" textheight="${fontSize}" baseline="${baseline}" spacing="${spacing}" horzpos="0" horzsize="${horzSize}" flags="${flags}"/>`
|
|
5001
5159
|
);
|
|
5002
5160
|
}
|
|
5003
5161
|
return {
|
|
@@ -5010,7 +5168,13 @@ function extractParaText(para) {
|
|
|
5010
5168
|
const walk = (kids) => {
|
|
5011
5169
|
for (const k of kids) {
|
|
5012
5170
|
if (k.tag === "span") {
|
|
5013
|
-
for (const c of k.kids)
|
|
5171
|
+
for (const c of k.kids) {
|
|
5172
|
+
if (c.tag === "txt") {
|
|
5173
|
+
text += c.content;
|
|
5174
|
+
} else if (c.tag === "br") {
|
|
5175
|
+
text += "\n";
|
|
5176
|
+
}
|
|
5177
|
+
}
|
|
5014
5178
|
} else if (k.tag === "link") {
|
|
5015
5179
|
walk(k.kids);
|
|
5016
5180
|
}
|
|
@@ -5069,7 +5233,7 @@ function encodeParaPositioned(para, ctx, vertPos, secPr = "", availWidth, hfRun
|
|
|
5069
5233
|
(k) => k.tag === "span" && k.kids.some((c) => c.tag === "pb")
|
|
5070
5234
|
);
|
|
5071
5235
|
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>`;
|
|
5072
|
-
return { xml, nextVertPos: vertPos + totalHeight };
|
|
5236
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak };
|
|
5073
5237
|
}
|
|
5074
5238
|
function encodeTablePara(para, grid, ctx, vertPos, secPr, hfRun) {
|
|
5075
5239
|
const paraPrId = ctx.paraPrMap.get(paraPrKey(para.props)) ?? 0;
|
|
@@ -5079,8 +5243,12 @@ function encodeTablePara(para, grid, ctx, vertPos, secPr, hfRun) {
|
|
|
5079
5243
|
const baseline = 850;
|
|
5080
5244
|
const spacing = Math.max(0, totalHeight - fontSize);
|
|
5081
5245
|
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>`;
|
|
5082
|
-
const
|
|
5083
|
-
|
|
5246
|
+
const hasPageBreak = para.kids.some(
|
|
5247
|
+
(k) => k.tag === "span" && k.kids.some((c) => c.tag === "pb")
|
|
5248
|
+
);
|
|
5249
|
+
const runId = ctx.nextElementId++;
|
|
5250
|
+
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>`;
|
|
5251
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak };
|
|
5084
5252
|
}
|
|
5085
5253
|
function encodeCodeBlockPositioned(para, ctx, vertPos, secPr, fontSize, spacing, vertSize) {
|
|
5086
5254
|
const codeBfId = ctx.borderFillBank.addUniform(
|
|
@@ -5101,7 +5269,7 @@ function encodeCodeBlockPositioned(para, ctx, vertPos, secPr, fontSize, spacing,
|
|
|
5101
5269
|
ctx.availableWidth
|
|
5102
5270
|
);
|
|
5103
5271
|
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>`;
|
|
5104
|
-
return { xml, nextVertPos: vertPos + totalHeight };
|
|
5272
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak: false };
|
|
5105
5273
|
}
|
|
5106
5274
|
function encodeParaKids(kids, ctx) {
|
|
5107
5275
|
let xml = "";
|
|
@@ -5150,8 +5318,7 @@ function encodeRunInner(span) {
|
|
|
5150
5318
|
const content = esc(kid.content);
|
|
5151
5319
|
if (content) xml += `<hp:t xml:space="preserve">${content}</hp:t>`;
|
|
5152
5320
|
} else if (kid.tag === "br") {
|
|
5153
|
-
xml += `<hp:
|
|
5154
|
-
</hp:t>`;
|
|
5321
|
+
xml += `<hp:br/>`;
|
|
5155
5322
|
} else if (kid.tag === "pagenum") {
|
|
5156
5323
|
const fmt = kid.format === "roman" ? "ROMAN_LOWER" : kid.format === "romanCaps" ? "ROMAN_UPPER" : "DIGIT";
|
|
5157
5324
|
xml += `<hp:pageNum pageStartsOn="BOTH" formatType="${fmt}"/>`;
|
|
@@ -5232,8 +5399,9 @@ function encodeGridPositioned(grid, ctx, vertPos, secPr = "", hfRun = "") {
|
|
|
5232
5399
|
const baseline = Math.round(fontSize * 0.83);
|
|
5233
5400
|
const spacing = Math.max(0, totalHeight - fontSize);
|
|
5234
5401
|
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>`;
|
|
5235
|
-
const
|
|
5236
|
-
|
|
5402
|
+
const runId = ctx.nextElementId++;
|
|
5403
|
+
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>`;
|
|
5404
|
+
return { xml, nextVertPos: vertPos + totalHeight, hasPageBreak: false };
|
|
5237
5405
|
}
|
|
5238
5406
|
function buildGridXml(grid, ctx) {
|
|
5239
5407
|
const rowCount = grid.kids.length;
|
|
@@ -5621,6 +5789,40 @@ function stylesXml() {
|
|
|
5621
5789
|
</w:pPr></w:pPrDefault>
|
|
5622
5790
|
</w:docDefaults>
|
|
5623
5791
|
<w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/></w:style>
|
|
5792
|
+
<w:style w:type="paragraph" w:styleId="0"><w:name w:val="\uBC14\uD0D5\uAE00"/><w:basedOn w:val="Normal"/></w:style>
|
|
5793
|
+
<w:style w:type="paragraph" w:styleId="1"><w:name w:val="\uBCF8\uBB38"/><w:basedOn w:val="Normal"/></w:style>
|
|
5794
|
+
<w:style w:type="paragraph" w:styleId="2"><w:name w:val="\uAC1C\uC694 1"/><w:basedOn w:val="Normal"/></w:style>
|
|
5795
|
+
<w:style w:type="paragraph" w:styleId="3"><w:name w:val="\uAC1C\uC694 2"/><w:basedOn w:val="Normal"/></w:style>
|
|
5796
|
+
<w:style w:type="paragraph" w:styleId="4"><w:name w:val="\uAC1C\uC694 3"/><w:basedOn w:val="Normal"/></w:style>
|
|
5797
|
+
<w:style w:type="paragraph" w:styleId="5"><w:name w:val="\uAC1C\uC694 4"/><w:basedOn w:val="Normal"/></w:style>
|
|
5798
|
+
<w:style w:type="paragraph" w:styleId="6"><w:name w:val="\uAC1C\uC694 5"/><w:basedOn w:val="Normal"/></w:style>
|
|
5799
|
+
<w:style w:type="paragraph" w:styleId="7"><w:name w:val="\uAC1C\uC694 6"/><w:basedOn w:val="Normal"/></w:style>
|
|
5800
|
+
<w:style w:type="paragraph" w:styleId="8"><w:name w:val="\uAC1C\uC694 7"/><w:basedOn w:val="Normal"/></w:style>
|
|
5801
|
+
<w:style w:type="paragraph" w:styleId="9"><w:name w:val="\uAC1C\uC694 8"/><w:basedOn w:val="Normal"/></w:style>
|
|
5802
|
+
<w:style w:type="paragraph" w:styleId="10"><w:name w:val="\uAC1C\uC694 9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5803
|
+
<w:style w:type="paragraph" w:styleId="11"><w:name w:val="\uAC1C\uC694 10"/><w:basedOn w:val="Normal"/></w:style>
|
|
5804
|
+
<w:style w:type="paragraph" w:styleId="12"><w:name w:val="\uCABD \uBC88\uD638"/><w:basedOn w:val="Normal"/></w:style>
|
|
5805
|
+
<w:style w:type="paragraph" w:styleId="13"><w:name w:val="\uBA38\uB9AC\uB9D0"/><w:basedOn w:val="Normal"/></w:style>
|
|
5806
|
+
<w:style w:type="paragraph" w:styleId="14"><w:name w:val="\uAC01\uC8FC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5807
|
+
<w:style w:type="paragraph" w:styleId="15"><w:name w:val="\uBBF8\uC8FC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5808
|
+
<w:style w:type="paragraph" w:styleId="16"><w:name w:val="\uBA54\uBAA8"/><w:basedOn w:val="Normal"/></w:style>
|
|
5809
|
+
<w:style w:type="paragraph" w:styleId="17"><w:name w:val="\uCC28\uB840 \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5810
|
+
<w:style w:type="paragraph" w:styleId="18"><w:name w:val="\uCC28\uB840 1"/><w:basedOn w:val="Normal"/></w:style>
|
|
5811
|
+
<w:style w:type="paragraph" w:styleId="19"><w:name w:val="\uCC28\uB840 2"/><w:basedOn w:val="Normal"/></w:style>
|
|
5812
|
+
<w:style w:type="paragraph" w:styleId="20"><w:name w:val="\uCC28\uB840 3"/><w:basedOn w:val="Normal"/></w:style>
|
|
5813
|
+
<w:style w:type="paragraph" w:styleId="21"><w:name w:val="\uBCF8\uBB38 \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5814
|
+
<w:style w:type="paragraph" w:styleId="22"><w:name w:val="\uADF8\uB9BC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5815
|
+
<w:style w:type="paragraph" w:styleId="23"><w:name w:val="\uD45C"/><w:basedOn w:val="Normal"/></w:style>
|
|
5816
|
+
<w:style w:type="paragraph" w:styleId="24"><w:name w:val="\uC218\uC2DD"/><w:basedOn w:val="Normal"/></w:style>
|
|
5817
|
+
<w:style w:type="paragraph" w:styleId="25"><w:name w:val="\uC778\uC6A9\uBB38"/><w:basedOn w:val="Normal"/></w:style>
|
|
5818
|
+
<w:style w:type="paragraph" w:styleId="26"><w:name w:val="\uB0A0\uC9DC"/><w:basedOn w:val="Normal"/></w:style>
|
|
5819
|
+
<w:style w:type="paragraph" w:styleId="27"><w:name w:val="\uBC1C\uC2E0\uBA85\uC758"/><w:basedOn w:val="Normal"/></w:style>
|
|
5820
|
+
<w:style w:type="paragraph" w:styleId="28"><w:name w:val="\uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5821
|
+
<w:style w:type="paragraph" w:styleId="29"><w:name w:val="\uBD80\uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5822
|
+
<w:style w:type="paragraph" w:styleId="30"><w:name w:val="\uBB38\uB2E8 \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5823
|
+
<w:style w:type="paragraph" w:styleId="31"><w:name w:val="MEMO"/><w:basedOn w:val="Normal"/></w:style>
|
|
5824
|
+
<w:style w:type="paragraph" w:styleId="32"><w:name w:val="\uAC1C\uC694"/><w:basedOn w:val="Normal"/></w:style>
|
|
5825
|
+
<w:style w:type="paragraph" w:styleId="33"><w:name w:val="\uD45C \uC81C\uBAA9"/><w:basedOn w:val="Normal"/></w:style>
|
|
5624
5826
|
<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>
|
|
5625
5827
|
<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>
|
|
5626
5828
|
<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>
|
|
@@ -5710,7 +5912,12 @@ function encodeContent(node, ctx, dims) {
|
|
|
5710
5912
|
}
|
|
5711
5913
|
function encodeParaInner(para, ctx) {
|
|
5712
5914
|
const align = para.props.align ?? "left";
|
|
5713
|
-
|
|
5915
|
+
let headStyle = "";
|
|
5916
|
+
if (para.props.hwpStyleId !== void 0) {
|
|
5917
|
+
headStyle = `<w:pStyle w:val="${para.props.hwpStyleId}"/>`;
|
|
5918
|
+
} else if (para.props.heading) {
|
|
5919
|
+
headStyle = `<w:pStyle w:val="Heading${para.props.heading}"/>`;
|
|
5920
|
+
}
|
|
5714
5921
|
let numPr = "";
|
|
5715
5922
|
if (para.props.listOrd !== void 0) {
|
|
5716
5923
|
const numId = para.props.listOrd ? 2 : 1;
|
|
@@ -5749,6 +5956,10 @@ function encodeParaInner(para, ctx) {
|
|
|
5749
5956
|
const runs = para.kids.map((k) => {
|
|
5750
5957
|
if (k.tag === "span") return encodeRun(k, ctx);
|
|
5751
5958
|
if (k.tag === "img") return encodeImage2(k, ctx);
|
|
5959
|
+
if (k.tag === "pagenum") {
|
|
5960
|
+
const instr = k.format === "total" ? " NUMPAGES " : " PAGE ";
|
|
5961
|
+
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>`;
|
|
5962
|
+
}
|
|
5752
5963
|
return "";
|
|
5753
5964
|
}).join("");
|
|
5754
5965
|
return ` <w:p>
|
|
@@ -5785,8 +5996,9 @@ function encodeRun(span, _ctx) {
|
|
|
5785
5996
|
);
|
|
5786
5997
|
}
|
|
5787
5998
|
} else if (kid.tag === "pagenum") {
|
|
5999
|
+
const instr = kid.format === "total" ? " NUMPAGES " : " PAGE ";
|
|
5788
6000
|
parts.push(
|
|
5789
|
-
`<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
|
|
6001
|
+
`<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>`
|
|
5790
6002
|
);
|
|
5791
6003
|
} else if (kid.tag === "br") {
|
|
5792
6004
|
parts.push(`<w:r><w:br/></w:r>`);
|
|
@@ -6576,10 +6788,11 @@ var BufWriter = class {
|
|
|
6576
6788
|
};
|
|
6577
6789
|
function mkRec(tag, level, data) {
|
|
6578
6790
|
const sz = data.length;
|
|
6579
|
-
const
|
|
6580
|
-
const
|
|
6791
|
+
const isLarge = sz >= 4095;
|
|
6792
|
+
const enc = isLarge ? 4095 : sz;
|
|
6793
|
+
const hdr = ((enc & 4095) * 1048576 | (level & 1023) << 10 | tag & 1023) >>> 0;
|
|
6581
6794
|
const w = new BufWriter().u32(hdr);
|
|
6582
|
-
if (
|
|
6795
|
+
if (isLarge) w.u32(sz);
|
|
6583
6796
|
w.bytes(data);
|
|
6584
6797
|
return w.build();
|
|
6585
6798
|
}
|
|
@@ -6894,7 +7107,7 @@ function buildDocInfoStream(bank, images = []) {
|
|
|
6894
7107
|
return concatU8(chunks);
|
|
6895
7108
|
}
|
|
6896
7109
|
function mkPageDef(dims) {
|
|
6897
|
-
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)).
|
|
7110
|
+
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();
|
|
6898
7111
|
}
|
|
6899
7112
|
function mkParaHeader(nchars, ctrlMask, psId, csCount, lineAlignCount = 0, instanceId = 0) {
|
|
6900
7113
|
return new BufWriter().u32(nchars).u32(ctrlMask).u16(psId).u8(0).u8(0).u16(csCount).u16(0).u16(lineAlignCount).u32(instanceId).u16(0).build();
|
|
@@ -7095,7 +7308,7 @@ function encodePara3(para, bank, lv, instanceId, availWidthHwp, mask = 0, vertPo
|
|
|
7095
7308
|
];
|
|
7096
7309
|
}
|
|
7097
7310
|
function mkTableCtrl(wHwp, hHwp, instanceId, align = "left") {
|
|
7098
|
-
const alignFlags = { left: 0, center: 1, right: 2, justify: 3 }[align] ?? 0;
|
|
7311
|
+
const alignFlags = { left: 0, center: 1, right: 2, justify: 3, distribute: 0, distribute_space: 0 }[align] ?? 0;
|
|
7099
7312
|
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();
|
|
7100
7313
|
}
|
|
7101
7314
|
function mkTableRecord(rowCnt, colCnt, rowHwp, bfId) {
|
|
@@ -7186,7 +7399,7 @@ function encodeGrid4(grid, bank, lv, idGen, availWidthHwp) {
|
|
|
7186
7399
|
const cellWidthHwp = Metric.ptToHwp(cwPt[c] ?? defColPt);
|
|
7187
7400
|
for (const para of paras) {
|
|
7188
7401
|
records.push(
|
|
7189
|
-
...encodePara3(para, bank, lv +
|
|
7402
|
+
...encodePara3(para, bank, lv + 1, idGen(), cellWidthHwp)
|
|
7190
7403
|
);
|
|
7191
7404
|
}
|
|
7192
7405
|
}
|
|
@@ -7428,6 +7641,7 @@ function buildHwpFileHeader() {
|
|
|
7428
7641
|
}
|
|
7429
7642
|
function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = []) {
|
|
7430
7643
|
const SS = 512;
|
|
7644
|
+
const MSS = 64;
|
|
7431
7645
|
const ENDOFCHAIN = 4294967294;
|
|
7432
7646
|
const FREESECT = 4294967295;
|
|
7433
7647
|
const FATSECT = 4294967293;
|
|
@@ -7436,71 +7650,150 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7436
7650
|
`FileHeader \uD06C\uAE30 \uBD80\uC871: ${fileHeaderData.length} (\uCD5C\uC18C 256)`
|
|
7437
7651
|
);
|
|
7438
7652
|
}
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7653
|
+
const streams = [];
|
|
7654
|
+
streams.push({
|
|
7655
|
+
name: "FileHeader",
|
|
7656
|
+
data: fileHeaderData,
|
|
7657
|
+
dirIdx: 1,
|
|
7658
|
+
isMini: fileHeaderData.length < 4096
|
|
7659
|
+
});
|
|
7660
|
+
streams.push({
|
|
7661
|
+
name: "DocInfo",
|
|
7662
|
+
data: docInfoData,
|
|
7663
|
+
dirIdx: 2,
|
|
7664
|
+
isMini: docInfoData.length < 4096
|
|
7665
|
+
});
|
|
7666
|
+
streams.push({
|
|
7667
|
+
name: "Section0",
|
|
7668
|
+
data: section0Data,
|
|
7669
|
+
dirIdx: 4,
|
|
7670
|
+
isMini: section0Data.length < 4096
|
|
7671
|
+
});
|
|
7672
|
+
for (let i = 0; i < binImages.length; i++) {
|
|
7673
|
+
const img = binImages[i];
|
|
7674
|
+
const name = `BIN${String(img.id).padStart(4, "0")}.${img.ext}`;
|
|
7675
|
+
streams.push({
|
|
7676
|
+
name,
|
|
7677
|
+
data: img.data,
|
|
7678
|
+
dirIdx: 6 + i,
|
|
7679
|
+
isMini: img.data.length < 4096
|
|
7680
|
+
});
|
|
7681
|
+
}
|
|
7682
|
+
const miniStreams = streams.filter((s) => s.isMini);
|
|
7683
|
+
const miniSectorList = [];
|
|
7684
|
+
let miniStreamDataLength = 0;
|
|
7685
|
+
for (const s of miniStreams) {
|
|
7686
|
+
const startSec = miniStreamDataLength / MSS;
|
|
7687
|
+
s.startSec = startSec;
|
|
7688
|
+
const len = s.data.length;
|
|
7689
|
+
const numMiniSecs = Math.ceil(len / MSS);
|
|
7690
|
+
for (let i = 0; i < numMiniSecs; i++) {
|
|
7691
|
+
const curSec2 = startSec + i;
|
|
7692
|
+
const nextSec = i === numMiniSecs - 1 ? ENDOFCHAIN : curSec2 + 1;
|
|
7693
|
+
while (miniSectorList.length <= curSec2) {
|
|
7694
|
+
miniSectorList.push(FREESECT);
|
|
7695
|
+
}
|
|
7696
|
+
miniSectorList[curSec2] = nextSec;
|
|
7697
|
+
}
|
|
7698
|
+
miniStreamDataLength += numMiniSecs * MSS;
|
|
7699
|
+
}
|
|
7700
|
+
const miniStreamData = new Uint8Array(miniStreamDataLength);
|
|
7701
|
+
let miniStreamOffset = 0;
|
|
7702
|
+
for (const s of miniStreams) {
|
|
7703
|
+
miniStreamData.set(s.data, miniStreamOffset);
|
|
7704
|
+
miniStreamOffset += Math.ceil(s.data.length / MSS) * MSS;
|
|
7705
|
+
}
|
|
7706
|
+
const regularStreams = streams.filter((s) => !s.isMini);
|
|
7707
|
+
const regPads = regularStreams.map((s) => {
|
|
7708
|
+
const len = s.data.length;
|
|
7709
|
+
const n = Math.ceil(Math.max(len, 1) / SS) * SS;
|
|
7442
7710
|
const out2 = new Uint8Array(n);
|
|
7443
|
-
out2.set(
|
|
7711
|
+
out2.set(s.data);
|
|
7444
7712
|
return out2;
|
|
7445
|
-
}
|
|
7446
|
-
const
|
|
7447
|
-
const diPad = padSector(docInfoData);
|
|
7448
|
-
const s0Pad = padSector(section0Data);
|
|
7449
|
-
const imgPads = binImages.map((img) => padSector(img.data));
|
|
7450
|
-
const fhN = fhPad.length / SS;
|
|
7451
|
-
const diN = diPad.length / SS;
|
|
7452
|
-
const s0N = s0Pad.length / SS;
|
|
7453
|
-
const imgNs = imgPads.map((p) => p.length / SS);
|
|
7454
|
-
const totalImgN = imgNs.reduce((s, n) => s + n, 0);
|
|
7713
|
+
});
|
|
7714
|
+
const regNs = regPads.map((p) => p.length / SS);
|
|
7455
7715
|
const numDirEntries = 5 + (binImages.length > 0 ? 1 + binImages.length : 0);
|
|
7456
|
-
const dirN = Math.max(
|
|
7716
|
+
const dirN = Math.max(1, Math.ceil(numDirEntries * 128 / SS));
|
|
7717
|
+
const miniFatN = Math.ceil(miniSectorList.length / 128);
|
|
7718
|
+
const miniStreamN = Math.ceil(miniStreamData.length / SS);
|
|
7719
|
+
const totalRegStreamN = regNs.reduce((a, b) => a + b, 0);
|
|
7720
|
+
const neededDataSec = dirN + miniFatN + miniStreamN + totalRegStreamN;
|
|
7457
7721
|
let fatN = 1;
|
|
7458
7722
|
for (let iter = 0; iter < 10; iter++) {
|
|
7459
|
-
const
|
|
7460
|
-
const
|
|
7461
|
-
if (
|
|
7462
|
-
fatN =
|
|
7463
|
-
}
|
|
7464
|
-
const
|
|
7465
|
-
const
|
|
7466
|
-
const
|
|
7467
|
-
const
|
|
7468
|
-
|
|
7469
|
-
let
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
}
|
|
7474
|
-
const totalSec = curSec;
|
|
7723
|
+
const totalSec2 = fatN + neededDataSec;
|
|
7724
|
+
const neededFat = Math.ceil(totalSec2 / 128);
|
|
7725
|
+
if (neededFat <= fatN) break;
|
|
7726
|
+
fatN = neededFat;
|
|
7727
|
+
}
|
|
7728
|
+
const totalSec = fatN + neededDataSec;
|
|
7729
|
+
const dirStartSec = fatN;
|
|
7730
|
+
const miniFatStartSec = dirStartSec + dirN;
|
|
7731
|
+
const miniStreamStartSec = miniFatStartSec + miniFatN;
|
|
7732
|
+
let curSec = miniStreamStartSec + miniStreamN;
|
|
7733
|
+
for (let i = 0; i < regularStreams.length; i++) {
|
|
7734
|
+
regularStreams[i].startSec = curSec;
|
|
7735
|
+
curSec += regNs[i];
|
|
7736
|
+
}
|
|
7475
7737
|
const fatBuf = new Uint8Array(fatN * SS).fill(255);
|
|
7476
7738
|
const setFat = (i, v) => {
|
|
7477
|
-
|
|
7478
|
-
fatBuf[
|
|
7479
|
-
fatBuf[
|
|
7480
|
-
fatBuf[
|
|
7739
|
+
const off = i * 4;
|
|
7740
|
+
fatBuf[off] = v & 255;
|
|
7741
|
+
fatBuf[off + 1] = v >>> 8 & 255;
|
|
7742
|
+
fatBuf[off + 2] = v >>> 16 & 255;
|
|
7743
|
+
fatBuf[off + 3] = v >>> 24 & 255;
|
|
7481
7744
|
};
|
|
7482
|
-
for (let i = 0; i < fatN; i++)
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
for (let i = 0; i <
|
|
7486
|
-
setFat(
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7745
|
+
for (let i = 0; i < fatN; i++) {
|
|
7746
|
+
setFat(i, FATSECT);
|
|
7747
|
+
}
|
|
7748
|
+
for (let i = 0; i < dirN; i++) {
|
|
7749
|
+
setFat(
|
|
7750
|
+
dirStartSec + i,
|
|
7751
|
+
i + 1 < dirN ? dirStartSec + i + 1 : ENDOFCHAIN
|
|
7752
|
+
);
|
|
7753
|
+
}
|
|
7754
|
+
if (miniFatN > 0) {
|
|
7755
|
+
for (let i = 0; i < miniFatN; i++) {
|
|
7756
|
+
setFat(
|
|
7757
|
+
miniFatStartSec + i,
|
|
7758
|
+
i + 1 < miniFatN ? miniFatStartSec + i + 1 : ENDOFCHAIN
|
|
7759
|
+
);
|
|
7760
|
+
}
|
|
7761
|
+
}
|
|
7762
|
+
if (miniStreamN > 0) {
|
|
7763
|
+
for (let i = 0; i < miniStreamN; i++) {
|
|
7764
|
+
setFat(
|
|
7765
|
+
miniStreamStartSec + i,
|
|
7766
|
+
i + 1 < miniStreamN ? miniStreamStartSec + i + 1 : ENDOFCHAIN
|
|
7767
|
+
);
|
|
7768
|
+
}
|
|
7769
|
+
}
|
|
7770
|
+
for (let i = 0; i < regularStreams.length; i++) {
|
|
7771
|
+
const s = regularStreams[i];
|
|
7772
|
+
const n = regNs[i];
|
|
7773
|
+
const start = s.startSec;
|
|
7774
|
+
for (let j = 0; j < n; j++) {
|
|
7775
|
+
setFat(start + j, j + 1 < n ? start + j + 1 : ENDOFCHAIN);
|
|
7776
|
+
}
|
|
7777
|
+
}
|
|
7778
|
+
const miniFatBuf = new Uint8Array(miniFatN * SS).fill(255);
|
|
7779
|
+
const setMiniFat = (i, v) => {
|
|
7780
|
+
const off = i * 4;
|
|
7781
|
+
miniFatBuf[off] = v & 255;
|
|
7782
|
+
miniFatBuf[off + 1] = v >>> 8 & 255;
|
|
7783
|
+
miniFatBuf[off + 2] = v >>> 16 & 255;
|
|
7784
|
+
miniFatBuf[off + 3] = v >>> 24 & 255;
|
|
7785
|
+
};
|
|
7786
|
+
for (let i = 0; i < miniSectorList.length; i++) {
|
|
7787
|
+
setMiniFat(i, miniSectorList[i]);
|
|
7496
7788
|
}
|
|
7497
7789
|
const dirBuf = new Uint8Array(dirN * SS);
|
|
7498
7790
|
const dv = new DataView(dirBuf.buffer);
|
|
7499
7791
|
function writeDirEntry(idx, name, type, left, right, child, startSec, size) {
|
|
7500
7792
|
const base = idx * 128;
|
|
7501
7793
|
const nl = name.length;
|
|
7502
|
-
for (let i = 0; i < nl; i++)
|
|
7794
|
+
for (let i = 0; i < nl; i++) {
|
|
7503
7795
|
dv.setUint16(base + i * 2, name.charCodeAt(i), true);
|
|
7796
|
+
}
|
|
7504
7797
|
dv.setUint16(base + 64, (nl + 1) * 2, true);
|
|
7505
7798
|
dirBuf[base + 66] = type;
|
|
7506
7799
|
dirBuf[base + 67] = 1;
|
|
@@ -7516,35 +7809,20 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7516
7809
|
dv.setInt32(base + 72, -1, true);
|
|
7517
7810
|
dv.setInt32(base + 76, -1, true);
|
|
7518
7811
|
}
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
writeDirEntry(2, "DocInfo", 2, -1, 3, -1, diSec, docInfoData.length);
|
|
7523
|
-
writeDirEntry(3, "BodyText", 1, -1, 5, 4, ENDOFCHAIN, 0);
|
|
7524
|
-
writeDirEntry(4, "Section0", 2, -1, -1, -1, s0Sec, section0Data.length);
|
|
7525
|
-
writeDirEntry(5, "BinData", 1, -1, -1, 6, ENDOFCHAIN, 0);
|
|
7526
|
-
for (let ii = 0; ii < binImages.length; ii++) {
|
|
7527
|
-
const img = binImages[ii];
|
|
7528
|
-
const streamName = `BIN${String(img.id).padStart(4, "0")}.${img.ext}`;
|
|
7529
|
-
const sibling = ii + 1 < binImages.length ? 7 + ii : -1;
|
|
7530
|
-
writeDirEntry(
|
|
7531
|
-
6 + ii,
|
|
7532
|
-
streamName,
|
|
7533
|
-
2,
|
|
7534
|
-
-1,
|
|
7535
|
-
sibling,
|
|
7536
|
-
-1,
|
|
7537
|
-
imgSecs[ii],
|
|
7538
|
-
img.data.length
|
|
7539
|
-
);
|
|
7540
|
-
}
|
|
7541
|
-
} else {
|
|
7542
|
-
writeDirEntry(0, "Root Entry", 5, -1, -1, 1, ENDOFCHAIN, 0);
|
|
7543
|
-
writeDirEntry(1, "FileHeader", 2, -1, 2, -1, fhSec, fileHeaderData.length);
|
|
7544
|
-
writeDirEntry(2, "DocInfo", 2, -1, 3, -1, diSec, docInfoData.length);
|
|
7545
|
-
writeDirEntry(3, "BodyText", 1, -1, -1, 4, ENDOFCHAIN, 0);
|
|
7546
|
-
writeDirEntry(4, "Section0", 2, -1, -1, -1, s0Sec, section0Data.length);
|
|
7812
|
+
const streamMap = /* @__PURE__ */ new Map();
|
|
7813
|
+
for (const s of streams) {
|
|
7814
|
+
streamMap.set(s.dirIdx, s);
|
|
7547
7815
|
}
|
|
7816
|
+
writeDirEntry(
|
|
7817
|
+
0,
|
|
7818
|
+
"Root Entry",
|
|
7819
|
+
5,
|
|
7820
|
+
-1,
|
|
7821
|
+
-1,
|
|
7822
|
+
3,
|
|
7823
|
+
miniStreamStartSec,
|
|
7824
|
+
miniStreamData.length
|
|
7825
|
+
);
|
|
7548
7826
|
const HWP_CLSID = [
|
|
7549
7827
|
32,
|
|
7550
7828
|
233,
|
|
@@ -7563,7 +7841,61 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7563
7841
|
155,
|
|
7564
7842
|
113
|
|
7565
7843
|
];
|
|
7566
|
-
for (let i = 0; i < 16; i++)
|
|
7844
|
+
for (let i = 0; i < 16; i++) {
|
|
7845
|
+
dirBuf[0 * 128 + 80 + i] = HWP_CLSID[i];
|
|
7846
|
+
}
|
|
7847
|
+
const fhStream = streamMap.get(1);
|
|
7848
|
+
writeDirEntry(
|
|
7849
|
+
1,
|
|
7850
|
+
"FileHeader",
|
|
7851
|
+
2,
|
|
7852
|
+
-1,
|
|
7853
|
+
-1,
|
|
7854
|
+
-1,
|
|
7855
|
+
fhStream.startSec,
|
|
7856
|
+
fhStream.data.length
|
|
7857
|
+
);
|
|
7858
|
+
const diStream = streamMap.get(2);
|
|
7859
|
+
const docInfoLeft = binImages.length > 0 ? 5 : -1;
|
|
7860
|
+
writeDirEntry(
|
|
7861
|
+
2,
|
|
7862
|
+
"DocInfo",
|
|
7863
|
+
2,
|
|
7864
|
+
docInfoLeft,
|
|
7865
|
+
-1,
|
|
7866
|
+
-1,
|
|
7867
|
+
diStream.startSec,
|
|
7868
|
+
diStream.data.length
|
|
7869
|
+
);
|
|
7870
|
+
writeDirEntry(3, "BodyText", 1, 2, 1, 4, ENDOFCHAIN, 0);
|
|
7871
|
+
const s0Stream = streamMap.get(4);
|
|
7872
|
+
writeDirEntry(
|
|
7873
|
+
4,
|
|
7874
|
+
"Section0",
|
|
7875
|
+
2,
|
|
7876
|
+
-1,
|
|
7877
|
+
-1,
|
|
7878
|
+
-1,
|
|
7879
|
+
s0Stream.startSec,
|
|
7880
|
+
s0Stream.data.length
|
|
7881
|
+
);
|
|
7882
|
+
if (binImages.length > 0) {
|
|
7883
|
+
writeDirEntry(5, "BinData", 1, -1, -1, 6, ENDOFCHAIN, 0);
|
|
7884
|
+
for (let i = 0; i < binImages.length; i++) {
|
|
7885
|
+
const imgStream = streamMap.get(6 + i);
|
|
7886
|
+
const sibling = i + 1 < binImages.length ? 7 + i : -1;
|
|
7887
|
+
writeDirEntry(
|
|
7888
|
+
6 + i,
|
|
7889
|
+
imgStream.name,
|
|
7890
|
+
2,
|
|
7891
|
+
-1,
|
|
7892
|
+
sibling,
|
|
7893
|
+
-1,
|
|
7894
|
+
imgStream.startSec,
|
|
7895
|
+
imgStream.data.length
|
|
7896
|
+
);
|
|
7897
|
+
}
|
|
7898
|
+
}
|
|
7567
7899
|
const hdr = new Uint8Array(SS);
|
|
7568
7900
|
const hdv = new DataView(hdr.buffer);
|
|
7569
7901
|
const MAGIC = [208, 207, 17, 224, 161, 177, 26, 225];
|
|
@@ -7572,32 +7904,43 @@ function buildHwpOle2(fileHeaderData, docInfoData, section0Data, binImages = [])
|
|
|
7572
7904
|
});
|
|
7573
7905
|
hdv.setUint16(24, 62, true);
|
|
7574
7906
|
hdv.setUint16(26, 3, true);
|
|
7575
|
-
hdv.setUint16(28,
|
|
7907
|
+
hdv.setUint16(28, 65534, true);
|
|
7576
7908
|
hdv.setUint16(30, 9, true);
|
|
7577
7909
|
hdv.setUint16(32, 6, true);
|
|
7578
|
-
hdv.setUint32(40,
|
|
7579
|
-
hdv.setUint32(44,
|
|
7580
|
-
hdv.setUint32(48,
|
|
7581
|
-
hdv.setUint32(52,
|
|
7582
|
-
hdv.setUint32(56,
|
|
7583
|
-
hdv.setUint32(60, 0, true);
|
|
7584
|
-
hdv.setUint32(64,
|
|
7585
|
-
hdv.setUint32(68,
|
|
7910
|
+
hdv.setUint32(40, 0, true);
|
|
7911
|
+
hdv.setUint32(44, fatN, true);
|
|
7912
|
+
hdv.setUint32(48, dirStartSec, true);
|
|
7913
|
+
hdv.setUint32(52, 0, true);
|
|
7914
|
+
hdv.setUint32(56, 4096, true);
|
|
7915
|
+
hdv.setUint32(60, miniFatN > 0 ? miniFatStartSec : ENDOFCHAIN, true);
|
|
7916
|
+
hdv.setUint32(64, miniFatN, true);
|
|
7917
|
+
hdv.setUint32(68, ENDOFCHAIN, true);
|
|
7586
7918
|
hdv.setUint32(72, 0, true);
|
|
7587
7919
|
for (let i = 0; i < 109; i++) {
|
|
7588
7920
|
hdv.setUint32(76 + i * 4, i < fatN ? i : FREESECT, true);
|
|
7589
7921
|
}
|
|
7590
7922
|
const out = new Uint8Array(SS + totalSec * SS);
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
out.set(
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7923
|
+
let outOff = 0;
|
|
7924
|
+
out.set(hdr, outOff);
|
|
7925
|
+
outOff += SS;
|
|
7926
|
+
out.set(fatBuf, outOff);
|
|
7927
|
+
outOff += fatN * SS;
|
|
7928
|
+
out.set(dirBuf, outOff);
|
|
7929
|
+
outOff += dirN * SS;
|
|
7930
|
+
if (miniFatN > 0) {
|
|
7931
|
+
out.set(miniFatBuf, outOff);
|
|
7932
|
+
outOff += miniFatN * SS;
|
|
7933
|
+
}
|
|
7934
|
+
if (miniStreamN > 0) {
|
|
7935
|
+
const miniStreamPad = new Uint8Array(miniStreamN * SS);
|
|
7936
|
+
miniStreamPad.set(miniStreamData);
|
|
7937
|
+
out.set(miniStreamPad, outOff);
|
|
7938
|
+
outOff += miniStreamN * SS;
|
|
7939
|
+
}
|
|
7940
|
+
for (let i = 0; i < regularStreams.length; i++) {
|
|
7941
|
+
out.set(regPads[i], outOff);
|
|
7942
|
+
outOff += regNs[i] * SS;
|
|
7943
|
+
}
|
|
7601
7944
|
return out;
|
|
7602
7945
|
}
|
|
7603
7946
|
function concatU8(arrays) {
|