kordoc 3.8.1 → 3.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/{-LD4BZDDJ.js → -FEHSMPVO.js} +3 -3
- package/dist/{chunk-PELBIL4K.js → chunk-553VTUVP.js} +2 -2
- package/dist/{chunk-KT2BCHXI.js → chunk-DP37KF2X.js} +834 -822
- package/dist/chunk-DP37KF2X.js.map +1 -0
- package/dist/{chunk-IFYJFWD2.js → chunk-JHZUFBUV.js} +2 -2
- package/dist/{chunk-LFCS3UVG.cjs → chunk-YBPNKFJW.cjs} +2 -2
- package/dist/{chunk-LFCS3UVG.cjs.map → chunk-YBPNKFJW.cjs.map} +1 -1
- package/dist/cli.js +4 -4
- package/dist/index.cjs +946 -934
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -8
- package/dist/index.d.ts +17 -8
- package/dist/index.js +833 -821
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +3 -3
- package/dist/{parser-FFEBMLSH.js → parser-KNQDRLZQ.js} +60 -20
- package/dist/parser-KNQDRLZQ.js.map +1 -0
- package/dist/{parser-XEDROIM7.js → parser-NR2TYGO3.js} +60 -20
- package/dist/parser-NR2TYGO3.js.map +1 -0
- package/dist/{parser-IXK5V7YG.cjs → parser-NS4ZPD7B.cjs} +77 -35
- package/dist/parser-NS4ZPD7B.cjs.map +1 -0
- package/dist/{watch-MAWCDNFI.js → watch-XCWADLPU.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-KT2BCHXI.js.map +0 -1
- package/dist/parser-FFEBMLSH.js.map +0 -1
- package/dist/parser-IXK5V7YG.cjs.map +0 -1
- package/dist/parser-XEDROIM7.js.map +0 -1
- /package/dist/{-LD4BZDDJ.js.map → -FEHSMPVO.js.map} +0 -0
- /package/dist/{chunk-PELBIL4K.js.map → chunk-553VTUVP.js.map} +0 -0
- /package/dist/{chunk-IFYJFWD2.js.map → chunk-JHZUFBUV.js.map} +0 -0
- /package/dist/{watch-MAWCDNFI.js.map → watch-XCWADLPU.js.map} +0 -0
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
sanitizeHref,
|
|
26
26
|
stripDtd,
|
|
27
27
|
toArrayBuffer
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-JHZUFBUV.js";
|
|
29
29
|
import {
|
|
30
30
|
parsePageRange
|
|
31
31
|
} from "./chunk-MOL7MDBG.js";
|
|
@@ -20404,53 +20404,112 @@ function mmToHwpunit(mm) {
|
|
|
20404
20404
|
return Math.round(mm * 7200 / 25.4);
|
|
20405
20405
|
}
|
|
20406
20406
|
|
|
20407
|
-
// src/
|
|
20408
|
-
|
|
20409
|
-
|
|
20410
|
-
|
|
20411
|
-
|
|
20412
|
-
|
|
20413
|
-
|
|
20407
|
+
// src/hwpx/gen-ids.ts
|
|
20408
|
+
var NS_SECTION = "http://www.hancom.co.kr/hwpml/2011/section";
|
|
20409
|
+
var NS_PARA = "http://www.hancom.co.kr/hwpml/2011/paragraph";
|
|
20410
|
+
var NS_HEAD = "http://www.hancom.co.kr/hwpml/2011/head";
|
|
20411
|
+
var NS_CORE = "http://www.hancom.co.kr/hwpml/2011/core";
|
|
20412
|
+
var NS_OPF = "http://www.idpf.org/2007/opf/";
|
|
20413
|
+
var NS_HPF = "http://www.hancom.co.kr/schema/2011/hpf";
|
|
20414
|
+
var NS_OCF = "urn:oasis:names:tc:opendocument:xmlns:container";
|
|
20415
|
+
var CHAR_NORMAL = 0;
|
|
20416
|
+
var CHAR_BOLD = 1;
|
|
20417
|
+
var CHAR_ITALIC = 2;
|
|
20418
|
+
var CHAR_BOLD_ITALIC = 3;
|
|
20419
|
+
var CHAR_CODE = 4;
|
|
20420
|
+
var CHAR_H1 = 5;
|
|
20421
|
+
var CHAR_H2 = 6;
|
|
20422
|
+
var CHAR_H3 = 7;
|
|
20423
|
+
var CHAR_H4 = 8;
|
|
20424
|
+
var CHAR_TABLE_HEADER = 9;
|
|
20425
|
+
var CHAR_QUOTE = 10;
|
|
20426
|
+
var PARA_NORMAL = 0;
|
|
20427
|
+
var PARA_H1 = 1;
|
|
20428
|
+
var PARA_H2 = 2;
|
|
20429
|
+
var PARA_H3 = 3;
|
|
20430
|
+
var PARA_H4 = 4;
|
|
20431
|
+
var PARA_CODE = 5;
|
|
20432
|
+
var PARA_QUOTE = 6;
|
|
20433
|
+
var PARA_LIST = 7;
|
|
20434
|
+
var DEFAULT_TEXT_COLOR = "#000000";
|
|
20435
|
+
function resolveTheme(theme) {
|
|
20436
|
+
return {
|
|
20437
|
+
h1: theme?.headingColors?.[1] ?? DEFAULT_TEXT_COLOR,
|
|
20438
|
+
h2: theme?.headingColors?.[2] ?? DEFAULT_TEXT_COLOR,
|
|
20439
|
+
h3: theme?.headingColors?.[3] ?? DEFAULT_TEXT_COLOR,
|
|
20440
|
+
h4: theme?.headingColors?.[4] ?? theme?.headingColors?.[3] ?? DEFAULT_TEXT_COLOR,
|
|
20441
|
+
body: theme?.bodyColor ?? DEFAULT_TEXT_COLOR,
|
|
20442
|
+
quote: theme?.quoteColor ?? DEFAULT_TEXT_COLOR,
|
|
20443
|
+
/** quoteColor가 명시되었는지 — blockquote charPr 분기에 사용 (baseline 호환) */
|
|
20444
|
+
hasQuoteOption: theme?.quoteColor !== void 0,
|
|
20445
|
+
tableHeader: theme?.tableHeaderColor ?? theme?.bodyColor ?? DEFAULT_TEXT_COLOR,
|
|
20446
|
+
tableHeaderBold: !!theme?.tableHeaderBold
|
|
20447
|
+
};
|
|
20414
20448
|
}
|
|
20415
|
-
function
|
|
20416
|
-
return
|
|
20449
|
+
function escapeXml(text) {
|
|
20450
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
20417
20451
|
}
|
|
20418
|
-
function
|
|
20419
|
-
|
|
20452
|
+
function headingParaPrId(level) {
|
|
20453
|
+
if (level === 1) return PARA_H1;
|
|
20454
|
+
if (level === 2) return PARA_H2;
|
|
20455
|
+
if (level === 3) return PARA_H3;
|
|
20456
|
+
return PARA_H4;
|
|
20420
20457
|
}
|
|
20421
|
-
|
|
20422
|
-
|
|
20423
|
-
if (
|
|
20424
|
-
|
|
20425
|
-
|
|
20426
|
-
|
|
20427
|
-
|
|
20428
|
-
|
|
20429
|
-
|
|
20430
|
-
|
|
20431
|
-
|
|
20432
|
-
|
|
20433
|
-
|
|
20434
|
-
|
|
20435
|
-
|
|
20436
|
-
|
|
20437
|
-
|
|
20438
|
-
|
|
20439
|
-
|
|
20440
|
-
|
|
20441
|
-
|
|
20442
|
-
|
|
20443
|
-
|
|
20444
|
-
|
|
20445
|
-
|
|
20446
|
-
|
|
20447
|
-
|
|
20458
|
+
function headingCharPrId(level) {
|
|
20459
|
+
if (level === 1) return CHAR_H1;
|
|
20460
|
+
if (level === 2) return CHAR_H2;
|
|
20461
|
+
if (level === 3) return CHAR_H3;
|
|
20462
|
+
return CHAR_H4;
|
|
20463
|
+
}
|
|
20464
|
+
function charPr(id, height, bold, italic, fontId = 0, textColor = DEFAULT_TEXT_COLOR, ratioPct = 100) {
|
|
20465
|
+
const boldAttr = bold ? ` bold="1"` : "";
|
|
20466
|
+
const italicAttr = italic ? ` italic="1"` : "";
|
|
20467
|
+
const effFont = bold ? 2 : fontId;
|
|
20468
|
+
return ` <hh:charPr id="${id}" height="${height}" textColor="${textColor}" shadeColor="none" useFontSpace="0" useKerning="0" symMark="NONE" borderFillIDRef="1"${boldAttr}${italicAttr}>
|
|
20469
|
+
<hh:fontRef hangul="${effFont}" latin="${effFont}" hanja="${effFont}" japanese="${effFont}" other="${effFont}" symbol="${effFont}" user="${effFont}"/>
|
|
20470
|
+
<hh:ratio hangul="${ratioPct}" latin="${ratioPct}" hanja="${ratioPct}" japanese="100" other="100" symbol="100" user="100"/>
|
|
20471
|
+
<hh:spacing hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
20472
|
+
<hh:relSz hangul="100" latin="100" hanja="100" japanese="100" other="100" symbol="100" user="100"/>
|
|
20473
|
+
<hh:offset hangul="0" latin="0" hanja="0" japanese="0" other="0" symbol="0" user="0"/>
|
|
20474
|
+
</hh:charPr>`;
|
|
20475
|
+
}
|
|
20476
|
+
function paraPr(id, opts = {}) {
|
|
20477
|
+
const { align = "JUSTIFY", spaceBefore = 0, spaceAfter = 0, lineSpacing = 160, indent = 0, left = 0, keepWord = false } = opts;
|
|
20478
|
+
const breakNonLatin = keepWord ? "KEEP_WORD" : "BREAK_WORD";
|
|
20479
|
+
const snapGrid = keepWord ? "0" : "1";
|
|
20480
|
+
return ` <hh:paraPr id="${id}" tabPrIDRef="0" condense="0" fontLineHeight="0" snapToGrid="${snapGrid}" suppressLineNumbers="0" checked="0" textDir="AUTO">
|
|
20481
|
+
<hh:align horizontal="${align}" vertical="BASELINE"/>
|
|
20482
|
+
<hh:heading type="NONE" idRef="0" level="0"/>
|
|
20483
|
+
<hh:breakSetting breakLatinWord="KEEP_WORD" breakNonLatinWord="${breakNonLatin}" widowOrphan="0" keepWithNext="0" keepLines="0" pageBreakBefore="0" lineWrap="BREAK"/>
|
|
20484
|
+
<hh:autoSpacing eAsianEng="0" eAsianNum="0"/>
|
|
20485
|
+
<hh:margin><hc:intent value="${indent}" unit="HWPUNIT"/><hc:left value="${left}" unit="HWPUNIT"/><hc:right value="0" unit="HWPUNIT"/><hc:prev value="${spaceBefore}" unit="HWPUNIT"/><hc:next value="${spaceAfter}" unit="HWPUNIT"/></hh:margin>
|
|
20486
|
+
<hh:lineSpacing type="PERCENT" value="${lineSpacing}"/>
|
|
20487
|
+
<hh:border borderFillIDRef="1" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/>
|
|
20488
|
+
</hh:paraPr>`;
|
|
20448
20489
|
}
|
|
20490
|
+
var GONGMUN_LIST_BASE = 8;
|
|
20491
|
+
var GONGMUN_LIST_LEVELS = 8;
|
|
20492
|
+
var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
|
|
20493
|
+
var CHAR_VARIANT_BASE = 11;
|
|
20494
|
+
var GONGMUN_BODY_RATIO = 95;
|
|
20449
20495
|
|
|
20450
|
-
// src/
|
|
20451
|
-
function
|
|
20496
|
+
// src/hwpx/md-runs.ts
|
|
20497
|
+
function buildPrvText(blocks) {
|
|
20498
|
+
const lines = [];
|
|
20499
|
+
let bytes = 0;
|
|
20500
|
+
for (const b of blocks) {
|
|
20501
|
+
let text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
|
|
20502
|
+
if (b.type === "html_table") text = text.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
20503
|
+
if (!text) continue;
|
|
20504
|
+
lines.push(text);
|
|
20505
|
+
bytes += text.length * 3;
|
|
20506
|
+
if (bytes > 1024) break;
|
|
20507
|
+
}
|
|
20508
|
+
return lines.join("\n").slice(0, 1024);
|
|
20509
|
+
}
|
|
20510
|
+
function parseMarkdownToBlocks(md2) {
|
|
20452
20511
|
const lines = md2.split("\n");
|
|
20453
|
-
const
|
|
20512
|
+
const blocks = [];
|
|
20454
20513
|
let i = 0;
|
|
20455
20514
|
while (i < lines.length) {
|
|
20456
20515
|
const line = lines[i];
|
|
@@ -20458,442 +20517,451 @@ function splitMarkdownUnits(md2) {
|
|
|
20458
20517
|
i++;
|
|
20459
20518
|
continue;
|
|
20460
20519
|
}
|
|
20461
|
-
|
|
20462
|
-
|
|
20520
|
+
const fenceMatch = line.match(/^(`{3,}|~{3,})(.*)$/);
|
|
20521
|
+
if (fenceMatch) {
|
|
20522
|
+
const fence = fenceMatch[1];
|
|
20523
|
+
const lang = fenceMatch[2].trim();
|
|
20524
|
+
const codeLines = [];
|
|
20525
|
+
i++;
|
|
20526
|
+
while (i < lines.length && !lines[i].startsWith(fence)) {
|
|
20527
|
+
codeLines.push(lines[i]);
|
|
20528
|
+
i++;
|
|
20529
|
+
}
|
|
20530
|
+
if (i < lines.length) i++;
|
|
20531
|
+
blocks.push({ type: "code_block", text: codeLines.join("\n"), lang });
|
|
20532
|
+
continue;
|
|
20533
|
+
}
|
|
20534
|
+
if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
|
|
20535
|
+
blocks.push({ type: "hr" });
|
|
20536
|
+
i++;
|
|
20537
|
+
continue;
|
|
20538
|
+
}
|
|
20539
|
+
const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
20540
|
+
if (headingMatch) {
|
|
20541
|
+
blocks.push({ type: "heading", text: headingMatch[2].trim(), level: headingMatch[1].length });
|
|
20542
|
+
i++;
|
|
20543
|
+
continue;
|
|
20544
|
+
}
|
|
20545
|
+
if (/^<table[\s>]/i.test(line.trimStart())) {
|
|
20546
|
+
const htmlLines = [];
|
|
20463
20547
|
let depth = 0;
|
|
20464
20548
|
while (i < lines.length) {
|
|
20465
20549
|
const l = lines[i];
|
|
20466
|
-
|
|
20467
|
-
depth += (l.match(/<table
|
|
20468
|
-
depth -= (l.match(/<\/table>/
|
|
20550
|
+
htmlLines.push(l);
|
|
20551
|
+
depth += (l.match(/<table[\s>]/gi) ?? []).length;
|
|
20552
|
+
depth -= (l.match(/<\/table>/gi) ?? []).length;
|
|
20469
20553
|
i++;
|
|
20470
20554
|
if (depth <= 0) break;
|
|
20471
20555
|
}
|
|
20472
|
-
|
|
20556
|
+
blocks.push({ type: "html_table", text: htmlLines.join("\n") });
|
|
20473
20557
|
continue;
|
|
20474
20558
|
}
|
|
20475
20559
|
if (line.trimStart().startsWith("|")) {
|
|
20476
|
-
const
|
|
20560
|
+
const tableRows = [];
|
|
20477
20561
|
while (i < lines.length && lines[i].trimStart().startsWith("|")) {
|
|
20478
|
-
|
|
20562
|
+
const row = lines[i];
|
|
20563
|
+
if (/^[\s|:\-]+$/.test(row)) {
|
|
20564
|
+
i++;
|
|
20565
|
+
continue;
|
|
20566
|
+
}
|
|
20567
|
+
const cells = row.split("|").slice(1, -1).map((c) => c.trim());
|
|
20568
|
+
if (cells.length > 0) tableRows.push(cells);
|
|
20479
20569
|
i++;
|
|
20480
20570
|
}
|
|
20481
|
-
|
|
20571
|
+
if (tableRows.length > 0) blocks.push({ type: "table", rows: tableRows });
|
|
20482
20572
|
continue;
|
|
20483
20573
|
}
|
|
20484
|
-
if (
|
|
20485
|
-
|
|
20486
|
-
i
|
|
20574
|
+
if (line.trimStart().startsWith("> ")) {
|
|
20575
|
+
const quoteLines = [];
|
|
20576
|
+
while (i < lines.length && (lines[i].trimStart().startsWith("> ") || lines[i].trimStart().startsWith(">"))) {
|
|
20577
|
+
quoteLines.push(lines[i].replace(/^>\s?/, ""));
|
|
20578
|
+
i++;
|
|
20579
|
+
}
|
|
20580
|
+
for (const ql of quoteLines) {
|
|
20581
|
+
blocks.push({ type: "blockquote", text: ql.trim() || "" });
|
|
20582
|
+
}
|
|
20487
20583
|
continue;
|
|
20488
20584
|
}
|
|
20489
|
-
|
|
20490
|
-
|
|
20585
|
+
const listMatch = line.match(/^(\s*)([-*+]|\d+[.)]) (.+)$/);
|
|
20586
|
+
if (listMatch) {
|
|
20587
|
+
const indent = Math.floor(listMatch[1].length / 2);
|
|
20588
|
+
const ordered = /\d/.test(listMatch[2]);
|
|
20589
|
+
blocks.push({ type: "list_item", text: listMatch[3].trim(), ordered, indent });
|
|
20491
20590
|
i++;
|
|
20492
20591
|
continue;
|
|
20493
20592
|
}
|
|
20494
|
-
|
|
20495
|
-
|
|
20496
|
-
collected.push(lines[i].trim());
|
|
20497
|
-
i++;
|
|
20498
|
-
}
|
|
20499
|
-
units.push({ kind: "text", raw: collected.join("\n"), lines: collected });
|
|
20593
|
+
blocks.push({ type: "paragraph", text: line.trim() });
|
|
20594
|
+
i++;
|
|
20500
20595
|
}
|
|
20501
|
-
return
|
|
20596
|
+
return blocks;
|
|
20502
20597
|
}
|
|
20503
|
-
function
|
|
20504
|
-
|
|
20505
|
-
|
|
20506
|
-
|
|
20507
|
-
|
|
20508
|
-
|
|
20509
|
-
|
|
20510
|
-
|
|
20598
|
+
function parseInlineMarkdown(text) {
|
|
20599
|
+
text = text.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1");
|
|
20600
|
+
text = text.replace(/\[([^\]]*)\]\(([^)]*)\)/g, (_, t, u) => t || u);
|
|
20601
|
+
text = text.replace(/~~([^~]+)~~/g, "$1");
|
|
20602
|
+
const spans = [];
|
|
20603
|
+
const regex = /(`[^`]+`|\*{3}[^*]+\*{3}|\*{2}[^*]+\*{2}|\*[^*]+\*|_{2}[^_]+_{2}|_[^_]+_)/g;
|
|
20604
|
+
let lastIdx = 0;
|
|
20605
|
+
for (const match of text.matchAll(regex)) {
|
|
20606
|
+
const idx = match.index;
|
|
20607
|
+
if (idx > lastIdx) {
|
|
20608
|
+
spans.push({ text: text.slice(lastIdx, idx), bold: false, italic: false, code: false });
|
|
20511
20609
|
}
|
|
20512
|
-
|
|
20513
|
-
|
|
20514
|
-
|
|
20515
|
-
if (
|
|
20516
|
-
|
|
20610
|
+
const raw = match[0];
|
|
20611
|
+
if (raw.startsWith("`")) {
|
|
20612
|
+
spans.push({ text: raw.slice(1, -1), bold: false, italic: false, code: true });
|
|
20613
|
+
} else if (raw.startsWith("***") || raw.startsWith("___")) {
|
|
20614
|
+
spans.push({ text: raw.slice(3, -3), bold: true, italic: true, code: false });
|
|
20615
|
+
} else if (raw.startsWith("**") || raw.startsWith("__")) {
|
|
20616
|
+
spans.push({ text: raw.slice(2, -2), bold: true, italic: false, code: false });
|
|
20517
20617
|
} else {
|
|
20518
|
-
|
|
20519
|
-
for (let j2 = 0; j2 < bMid; j2++) result2.push([null, pre + j2]);
|
|
20618
|
+
spans.push({ text: raw.slice(1, -1), bold: false, italic: true, code: false });
|
|
20520
20619
|
}
|
|
20521
|
-
|
|
20522
|
-
return result2;
|
|
20620
|
+
lastIdx = idx + raw.length;
|
|
20523
20621
|
}
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
for (let j2 = 1; j2 <= n; j2++) {
|
|
20527
|
-
dp[i2][j2] = a[i2 - 1] === b[j2 - 1] ? dp[i2 - 1][j2 - 1] + 1 : Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
20528
|
-
}
|
|
20529
|
-
}
|
|
20530
|
-
const matches = [];
|
|
20531
|
-
let i = m, j = n;
|
|
20532
|
-
while (i > 0 && j > 0) {
|
|
20533
|
-
if (a[i - 1] === b[j - 1] && dp[i][j] === dp[i - 1][j - 1] + 1) {
|
|
20534
|
-
matches.push([i - 1, j - 1]);
|
|
20535
|
-
i--;
|
|
20536
|
-
j--;
|
|
20537
|
-
} else if (dp[i - 1][j] >= dp[i][j - 1]) i--;
|
|
20538
|
-
else j--;
|
|
20622
|
+
if (lastIdx < text.length) {
|
|
20623
|
+
spans.push({ text: text.slice(lastIdx), bold: false, italic: false, code: false });
|
|
20539
20624
|
}
|
|
20540
|
-
|
|
20541
|
-
|
|
20542
|
-
let ai = 0, bi = 0;
|
|
20543
|
-
const flushGap = (aEnd, bEnd) => {
|
|
20544
|
-
if (aEnd - ai === bEnd - bi) {
|
|
20545
|
-
while (ai < aEnd) result.push([ai++, bi++]);
|
|
20546
|
-
return;
|
|
20547
|
-
}
|
|
20548
|
-
while (ai < aEnd && bi < bEnd) {
|
|
20549
|
-
const sim = normalizedSimilarity(a[ai], b[bi]);
|
|
20550
|
-
if (sim >= 0.4) {
|
|
20551
|
-
if (aEnd - ai > bEnd - bi && bestSimInRange(a, ai + 1, ai + (aEnd - ai) - (bEnd - bi), b[bi]) > sim) {
|
|
20552
|
-
result.push([ai++, null]);
|
|
20553
|
-
} else if (bEnd - bi > aEnd - ai && bestSimInRange(b, bi + 1, bi + (bEnd - bi) - (aEnd - ai), a[ai]) > sim) {
|
|
20554
|
-
result.push([null, bi++]);
|
|
20555
|
-
} else {
|
|
20556
|
-
result.push([ai++, bi++]);
|
|
20557
|
-
}
|
|
20558
|
-
} else if (aEnd - ai >= bEnd - bi) result.push([ai++, null]);
|
|
20559
|
-
else result.push([null, bi++]);
|
|
20560
|
-
}
|
|
20561
|
-
while (ai < aEnd) result.push([ai++, null]);
|
|
20562
|
-
while (bi < bEnd) result.push([null, bi++]);
|
|
20563
|
-
};
|
|
20564
|
-
for (const [pi, pj] of matches) {
|
|
20565
|
-
flushGap(pi, pj);
|
|
20566
|
-
result.push([ai++, bi++]);
|
|
20625
|
+
if (spans.length === 0) {
|
|
20626
|
+
spans.push({ text, bold: false, italic: false, code: false });
|
|
20567
20627
|
}
|
|
20568
|
-
|
|
20569
|
-
return result;
|
|
20628
|
+
return spans;
|
|
20570
20629
|
}
|
|
20571
|
-
function
|
|
20572
|
-
|
|
20573
|
-
|
|
20574
|
-
|
|
20575
|
-
|
|
20576
|
-
|
|
20577
|
-
return best;
|
|
20630
|
+
function spanToCharPrId(span) {
|
|
20631
|
+
if (span.code) return CHAR_CODE;
|
|
20632
|
+
if (span.bold && span.italic) return CHAR_BOLD_ITALIC;
|
|
20633
|
+
if (span.bold) return CHAR_BOLD;
|
|
20634
|
+
if (span.italic) return CHAR_ITALIC;
|
|
20635
|
+
return CHAR_NORMAL;
|
|
20578
20636
|
}
|
|
20579
|
-
function
|
|
20580
|
-
|
|
20637
|
+
function generateRuns(text, defaultCharPr = CHAR_NORMAL, mapCharId) {
|
|
20638
|
+
const spans = parseInlineMarkdown(text);
|
|
20639
|
+
return spans.map((span) => {
|
|
20640
|
+
let charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
|
|
20641
|
+
if (mapCharId) charId = mapCharId(charId);
|
|
20642
|
+
return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
|
|
20643
|
+
}).join("");
|
|
20581
20644
|
}
|
|
20582
|
-
|
|
20583
|
-
|
|
20584
|
-
|
|
20585
|
-
if (result.length <= 30 && result.includes(" ")) {
|
|
20586
|
-
const tokens = result.split(" ");
|
|
20587
|
-
const koreanSingleCharCount = tokens.filter((t) => t.length === 1 && /[가-ㄱ-ㆎ]/.test(t)).length;
|
|
20588
|
-
if (tokens.length >= 3 && koreanSingleCharCount / tokens.length >= 0.7) {
|
|
20589
|
-
result = tokens.join("");
|
|
20590
|
-
}
|
|
20645
|
+
function generateParagraph(text, paraPrId = PARA_NORMAL, charPrId = CHAR_NORMAL, mapCharId) {
|
|
20646
|
+
if (paraPrId === PARA_CODE) {
|
|
20647
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0"><hp:run charPrIDRef="${CHAR_CODE}"><hp:t>${escapeXml(text)}</hp:t></hp:run></hp:p>`;
|
|
20591
20648
|
}
|
|
20592
|
-
|
|
20593
|
-
}
|
|
20594
|
-
function normForMatch(text) {
|
|
20595
|
-
return sanitizeText(text).replace(/\s+/g, " ").trim();
|
|
20649
|
+
const runs = generateRuns(text, charPrId, mapCharId);
|
|
20650
|
+
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs}</hp:p>`;
|
|
20596
20651
|
}
|
|
20597
|
-
|
|
20598
|
-
|
|
20652
|
+
|
|
20653
|
+
// src/hwpx/gen-header.ts
|
|
20654
|
+
function generateContainerXml() {
|
|
20655
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
20656
|
+
<ocf:container xmlns:ocf="${NS_OCF}" xmlns:hpf="${NS_HPF}">
|
|
20657
|
+
<ocf:rootfiles>
|
|
20658
|
+
<ocf:rootfile full-path="Contents/content.hpf" media-type="application/hwpml-package+xml"/>
|
|
20659
|
+
</ocf:rootfiles>
|
|
20660
|
+
</ocf:container>`;
|
|
20599
20661
|
}
|
|
20600
|
-
function
|
|
20601
|
-
|
|
20602
|
-
|
|
20662
|
+
function generateManifest() {
|
|
20663
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
20664
|
+
<opf:package xmlns:opf="${NS_OPF}" xmlns:hpf="${NS_HPF}" xmlns:hh="${NS_HEAD}">
|
|
20665
|
+
<opf:manifest>
|
|
20666
|
+
<opf:item id="header" href="Contents/header.xml" media-type="application/xml"/>
|
|
20667
|
+
<opf:item id="section0" href="Contents/section0.xml" media-type="application/xml"/>
|
|
20668
|
+
</opf:manifest>
|
|
20669
|
+
<opf:spine>
|
|
20670
|
+
<opf:itemref idref="header" linear="no"/>
|
|
20671
|
+
<opf:itemref idref="section0" linear="yes"/>
|
|
20672
|
+
</opf:spine>
|
|
20673
|
+
</opf:package>`;
|
|
20603
20674
|
}
|
|
20604
|
-
function
|
|
20605
|
-
|
|
20606
|
-
if (
|
|
20607
|
-
|
|
20608
|
-
|
|
20609
|
-
|
|
20610
|
-
|
|
20611
|
-
|
|
20612
|
-
|
|
20613
|
-
if (skip.has(`${r},${c}`)) continue;
|
|
20614
|
-
const cell = cells[r]?.[c];
|
|
20615
|
-
if (!cell) continue;
|
|
20616
|
-
display[r][c] = {
|
|
20617
|
-
text: escapeGfm(sanitizeText(cell.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
|
|
20618
|
-
gridR: r,
|
|
20619
|
-
gridC: c
|
|
20620
|
-
};
|
|
20621
|
-
for (let dr = 0; dr < cell.rowSpan; dr++) {
|
|
20622
|
-
for (let dc = 0; dc < cell.colSpan; dc++) {
|
|
20623
|
-
if (dr === 0 && dc === 0) continue;
|
|
20624
|
-
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
20625
|
-
}
|
|
20626
|
-
}
|
|
20627
|
-
c += cell.colSpan - 1;
|
|
20628
|
-
}
|
|
20675
|
+
function buildCharProperties(theme, gongmun, ratioVariants = []) {
|
|
20676
|
+
let body = 1e3, code = 900, h1 = 1800, h2 = 1400, h3 = 1200, h4 = 1100;
|
|
20677
|
+
if (gongmun) {
|
|
20678
|
+
body = gongmun.bodyHeight;
|
|
20679
|
+
code = Math.max(body - 200, 900);
|
|
20680
|
+
h1 = gongmun.preset === "report" || gongmun.preset === "plan" ? 2e3 : 1700;
|
|
20681
|
+
h2 = 1600;
|
|
20682
|
+
h3 = body;
|
|
20683
|
+
h4 = Math.max(body - 100, 1300);
|
|
20629
20684
|
}
|
|
20630
|
-
const
|
|
20631
|
-
|
|
20632
|
-
|
|
20633
|
-
|
|
20634
|
-
|
|
20635
|
-
|
|
20636
|
-
|
|
20637
|
-
|
|
20638
|
-
|
|
20639
|
-
|
|
20640
|
-
|
|
20641
|
-
|
|
20642
|
-
|
|
20643
|
-
|
|
20644
|
-
|
|
20645
|
-
|
|
20646
|
-
|
|
20647
|
-
|
|
20685
|
+
const bodyRatio = gongmun ? GONGMUN_BODY_RATIO : 100;
|
|
20686
|
+
const rows = [
|
|
20687
|
+
charPr(0, body, false, false, 0, theme.body, bodyRatio),
|
|
20688
|
+
charPr(1, body, true, false, 0, theme.body, bodyRatio),
|
|
20689
|
+
charPr(2, body, false, true, 0, theme.body, bodyRatio),
|
|
20690
|
+
charPr(3, body, true, true, 0, theme.body, bodyRatio),
|
|
20691
|
+
charPr(4, code, false, false, 1),
|
|
20692
|
+
charPr(5, h1, true, false, 1, theme.h1),
|
|
20693
|
+
charPr(6, h2, true, false, 1, theme.h2),
|
|
20694
|
+
charPr(7, h3, true, false, 1, theme.h3),
|
|
20695
|
+
charPr(8, h4, true, false, 1, theme.h4),
|
|
20696
|
+
charPr(CHAR_TABLE_HEADER, body, theme.tableHeaderBold, false, 0, theme.tableHeader),
|
|
20697
|
+
charPr(CHAR_QUOTE, body, false, true, 0, theme.quote)
|
|
20698
|
+
];
|
|
20699
|
+
for (const r of ratioVariants) {
|
|
20700
|
+
rows.push(
|
|
20701
|
+
charPr(rows.length, body, false, false, 0, theme.body, r),
|
|
20702
|
+
charPr(rows.length + 1, body, true, false, 0, theme.body, r),
|
|
20703
|
+
charPr(rows.length + 2, body, false, true, 0, theme.body, r),
|
|
20704
|
+
charPr(rows.length + 3, body, true, true, 0, theme.body, r)
|
|
20705
|
+
);
|
|
20648
20706
|
}
|
|
20649
|
-
|
|
20650
|
-
|
|
20707
|
+
return `<hh:charProperties itemCnt="${rows.length}">
|
|
20708
|
+
${rows.join("\n")}
|
|
20709
|
+
</hh:charProperties>`;
|
|
20651
20710
|
}
|
|
20652
|
-
function
|
|
20653
|
-
|
|
20654
|
-
|
|
20655
|
-
|
|
20656
|
-
|
|
20657
|
-
|
|
20658
|
-
|
|
20659
|
-
|
|
20660
|
-
|
|
20711
|
+
function buildParaProperties(gongmun) {
|
|
20712
|
+
if (!gongmun) {
|
|
20713
|
+
const base2 = [
|
|
20714
|
+
paraPr(0),
|
|
20715
|
+
paraPr(1, { align: "LEFT", spaceBefore: 800, spaceAfter: 200, lineSpacing: 180 }),
|
|
20716
|
+
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: 170 }),
|
|
20717
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: 160 }),
|
|
20718
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160 }),
|
|
20719
|
+
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400 }),
|
|
20720
|
+
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600 }),
|
|
20721
|
+
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600 })
|
|
20722
|
+
];
|
|
20723
|
+
return `<hh:paraProperties itemCnt="${base2.length}">
|
|
20724
|
+
${base2.join("\n")}
|
|
20725
|
+
</hh:paraProperties>`;
|
|
20661
20726
|
}
|
|
20662
|
-
|
|
20663
|
-
|
|
20664
|
-
|
|
20665
|
-
|
|
20666
|
-
}
|
|
20667
|
-
|
|
20668
|
-
|
|
20669
|
-
|
|
20670
|
-
|
|
20671
|
-
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
|
|
20677
|
-
|
|
20727
|
+
const ls = gongmun.lineSpacing;
|
|
20728
|
+
const titleAlign = gongmun.centerTitle ? "CENTER" : "LEFT";
|
|
20729
|
+
const base = [
|
|
20730
|
+
paraPr(0, { lineSpacing: ls, keepWord: true }),
|
|
20731
|
+
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true }),
|
|
20732
|
+
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: ls, keepWord: true }),
|
|
20733
|
+
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
20734
|
+
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
20735
|
+
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
20736
|
+
paraPr(6, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true }),
|
|
20737
|
+
paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
|
|
20738
|
+
];
|
|
20739
|
+
for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
|
|
20740
|
+
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering);
|
|
20741
|
+
const sectionGap = gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
20742
|
+
base.push(paraPr(GONGMUN_LIST_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true }));
|
|
20678
20743
|
}
|
|
20679
|
-
|
|
20744
|
+
base.push(paraPr(GONGMUN_CENTER, { align: "CENTER", lineSpacing: ls, keepWord: true }));
|
|
20745
|
+
return `<hh:paraProperties itemCnt="${base.length}">
|
|
20746
|
+
${base.join("\n")}
|
|
20747
|
+
</hh:paraProperties>`;
|
|
20680
20748
|
}
|
|
20681
|
-
function
|
|
20682
|
-
const
|
|
20683
|
-
const
|
|
20684
|
-
|
|
20685
|
-
|
|
20686
|
-
|
|
20687
|
-
|
|
20688
|
-
|
|
20689
|
-
|
|
20690
|
-
|
|
20691
|
-
|
|
20692
|
-
|
|
20693
|
-
|
|
20694
|
-
|
|
20695
|
-
|
|
20696
|
-
|
|
20749
|
+
function generateHeaderXml(theme, gongmun, ratioVariants = []) {
|
|
20750
|
+
const bodyFace = gongmun?.bodyFont === "gothic" ? "\uB9D1\uC740 \uACE0\uB515" : "\uD568\uCD08\uB86C\uBC14\uD0D5";
|
|
20751
|
+
const charPropsXml = buildCharProperties(theme, gongmun, ratioVariants);
|
|
20752
|
+
const paraPropsXml = buildParaProperties(gongmun);
|
|
20753
|
+
return `<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
|
20754
|
+
<hh:head xmlns:hh="${NS_HEAD}" xmlns:hp="${NS_PARA}" xmlns:hc="${NS_CORE}" version="1.4" secCnt="1">
|
|
20755
|
+
<hh:beginNum page="1" footnote="1" endnote="1" pic="1" tbl="1" equation="1"/>
|
|
20756
|
+
<hh:refList>
|
|
20757
|
+
<hh:fontfaces itemCnt="7">
|
|
20758
|
+
<hh:fontface lang="HANGUL" fontCnt="3">
|
|
20759
|
+
<hh:font id="0" face="${bodyFace}" type="TTF" isEmbedded="0">
|
|
20760
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20761
|
+
</hh:font>
|
|
20762
|
+
<hh:font id="1" face="\uD568\uCD08\uB86C\uB3CB\uC6C0" type="TTF" isEmbedded="0">
|
|
20763
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20764
|
+
</hh:font>
|
|
20765
|
+
<hh:font id="2" face="HY\uACAC\uACE0\uB515" type="TTF" isEmbedded="0">
|
|
20766
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="9" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20767
|
+
</hh:font>
|
|
20768
|
+
</hh:fontface>
|
|
20769
|
+
<hh:fontface lang="LATIN" fontCnt="3">
|
|
20770
|
+
<hh:font id="0" face="Times New Roman" type="TTF" isEmbedded="0">
|
|
20771
|
+
<hh:typeInfo familyType="FCAT_OLDSTYLE" weight="5" proportion="4" contrast="2" strokeVariation="0" armStyle="0" letterform="0" midline="0" xHeight="4"/>
|
|
20772
|
+
</hh:font>
|
|
20773
|
+
<hh:font id="1" face="Consolas" type="TTF" isEmbedded="0">
|
|
20774
|
+
<hh:typeInfo familyType="FCAT_MODERN" weight="5" proportion="0" contrast="0" strokeVariation="0" armStyle="0" letterform="0" midline="0" xHeight="0"/>
|
|
20775
|
+
</hh:font>
|
|
20776
|
+
<hh:font id="2" face="Arial Black" type="TTF" isEmbedded="0">
|
|
20777
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="9" proportion="0" contrast="0" strokeVariation="0" armStyle="0" letterform="0" midline="0" xHeight="0"/>
|
|
20778
|
+
</hh:font>
|
|
20779
|
+
</hh:fontface>
|
|
20780
|
+
<hh:fontface lang="HANJA" fontCnt="1">
|
|
20781
|
+
<hh:font id="0" face="\uD568\uCD08\uB86C\uBC14\uD0D5" type="TTF" isEmbedded="0">
|
|
20782
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20783
|
+
</hh:font>
|
|
20784
|
+
</hh:fontface>
|
|
20785
|
+
<hh:fontface lang="JAPANESE" fontCnt="1">
|
|
20786
|
+
<hh:font id="0" face="\uAD74\uB9BC" type="TTF" isEmbedded="0">
|
|
20787
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20788
|
+
</hh:font>
|
|
20789
|
+
</hh:fontface>
|
|
20790
|
+
<hh:fontface lang="OTHER" fontCnt="1">
|
|
20791
|
+
<hh:font id="0" face="\uAD74\uB9BC" type="TTF" isEmbedded="0">
|
|
20792
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20793
|
+
</hh:font>
|
|
20794
|
+
</hh:fontface>
|
|
20795
|
+
<hh:fontface lang="SYMBOL" fontCnt="1">
|
|
20796
|
+
<hh:font id="0" face="Symbol" type="TTF" isEmbedded="0">
|
|
20797
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20798
|
+
</hh:font>
|
|
20799
|
+
</hh:fontface>
|
|
20800
|
+
<hh:fontface lang="USER" fontCnt="1">
|
|
20801
|
+
<hh:font id="0" face="\uAD74\uB9BC" type="TTF" isEmbedded="0">
|
|
20802
|
+
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
20803
|
+
</hh:font>
|
|
20804
|
+
</hh:fontface>
|
|
20805
|
+
</hh:fontfaces>
|
|
20806
|
+
<hh:borderFills itemCnt="2">
|
|
20807
|
+
<hh:borderFill id="1" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
20808
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
20809
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
20810
|
+
<hh:leftBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
20811
|
+
<hh:rightBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
20812
|
+
<hh:topBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
20813
|
+
<hh:bottomBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
20814
|
+
</hh:borderFill>
|
|
20815
|
+
<hh:borderFill id="2" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
20816
|
+
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
20817
|
+
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
20818
|
+
<hh:leftBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
20819
|
+
<hh:rightBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
20820
|
+
<hh:topBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
20821
|
+
<hh:bottomBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
20822
|
+
</hh:borderFill>
|
|
20823
|
+
</hh:borderFills>
|
|
20824
|
+
${charPropsXml}
|
|
20825
|
+
<hh:tabProperties itemCnt="0"/>
|
|
20826
|
+
<hh:numberings itemCnt="0"/>
|
|
20827
|
+
<hh:bullets itemCnt="0"/>
|
|
20828
|
+
${paraPropsXml}
|
|
20829
|
+
<hh:styles itemCnt="1">
|
|
20830
|
+
<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>
|
|
20831
|
+
</hh:styles>
|
|
20832
|
+
</hh:refList>
|
|
20833
|
+
<hh:compatibleDocument targetProgram="HWP2018"><hh:layoutCompatibility/></hh:compatibleDocument>
|
|
20834
|
+
</hh:head>`;
|
|
20697
20835
|
}
|
|
20698
|
-
|
|
20699
|
-
|
|
20700
|
-
|
|
20701
|
-
|
|
20702
|
-
|
|
20703
|
-
|
|
20704
|
-
|
|
20705
|
-
|
|
20706
|
-
|
|
20707
|
-
|
|
20708
|
-
|
|
20709
|
-
|
|
20710
|
-
|
|
20711
|
-
|
|
20712
|
-
|
|
20713
|
-
|
|
20714
|
-
|
|
20715
|
-
|
|
20716
|
-
|
|
20717
|
-
|
|
20718
|
-
|
|
20719
|
-
|
|
20720
|
-
|
|
20721
|
-
|
|
20836
|
+
|
|
20837
|
+
// src/hwpx/gen-gongmun-fit.ts
|
|
20838
|
+
function plainRenderText(text) {
|
|
20839
|
+
return parseInlineMarkdown(text).map((s) => s.text).join("");
|
|
20840
|
+
}
|
|
20841
|
+
function computeGongmunFitPlan(blocks, gongmun, gongmunList) {
|
|
20842
|
+
const minRatio = gongmun.autoFitMinRatio;
|
|
20843
|
+
if (minRatio === null || minRatio >= GONGMUN_BODY_RATIO) return null;
|
|
20844
|
+
const pageW = 59528 - mmToHwpunit(gongmun.margins.left) - mmToHwpunit(gongmun.margins.right);
|
|
20845
|
+
const ratioByBlock = /* @__PURE__ */ new Map();
|
|
20846
|
+
const variants = [];
|
|
20847
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
20848
|
+
const block = blocks[i];
|
|
20849
|
+
let text;
|
|
20850
|
+
let firstW;
|
|
20851
|
+
let contW;
|
|
20852
|
+
if (block.type === "list_item" && gongmunList.has(i)) {
|
|
20853
|
+
const { marker, depth } = gongmunList.get(i);
|
|
20854
|
+
const content = plainRenderText(block.text || "");
|
|
20855
|
+
text = marker ? `${marker} ${content}` : content;
|
|
20856
|
+
const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
|
|
20857
|
+
firstW = pageW - left - Math.max(indent, 0);
|
|
20858
|
+
contW = pageW - left - Math.max(-indent, 0);
|
|
20859
|
+
} else if (block.type === "paragraph") {
|
|
20860
|
+
const raw = (block.text || "").trim();
|
|
20861
|
+
if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
|
|
20862
|
+
text = plainRenderText(raw);
|
|
20863
|
+
firstW = contW = pageW;
|
|
20864
|
+
} else {
|
|
20865
|
+
continue;
|
|
20722
20866
|
}
|
|
20723
|
-
if (
|
|
20867
|
+
if (!text) continue;
|
|
20868
|
+
const r = fitRatioForFewerLines(text, firstW, contW, gongmun.bodyHeight, GONGMUN_BODY_RATIO, minRatio);
|
|
20869
|
+
if (r === null) continue;
|
|
20870
|
+
ratioByBlock.set(i, r);
|
|
20871
|
+
if (!variants.includes(r)) variants.push(r);
|
|
20724
20872
|
}
|
|
20725
|
-
return
|
|
20873
|
+
return ratioByBlock.size > 0 ? { ratioByBlock, variants } : null;
|
|
20726
20874
|
}
|
|
20727
|
-
function
|
|
20728
|
-
const
|
|
20729
|
-
|
|
20730
|
-
|
|
20731
|
-
|
|
20732
|
-
|
|
20733
|
-
|
|
20734
|
-
|
|
20735
|
-
|
|
20736
|
-
|
|
20737
|
-
|
|
20738
|
-
|
|
20739
|
-
if (tag === "table") {
|
|
20740
|
-
depth += isClose ? -1 : 1;
|
|
20741
|
-
if (depth < 0) return null;
|
|
20875
|
+
function variantMapper(fit, blockIdx) {
|
|
20876
|
+
const r = fit.ratioByBlock.get(blockIdx);
|
|
20877
|
+
if (r === void 0) return void 0;
|
|
20878
|
+
const vi = fit.variants.indexOf(r);
|
|
20879
|
+
return (id) => id >= 0 && id <= 3 ? CHAR_VARIANT_BASE + vi * 4 + id : id;
|
|
20880
|
+
}
|
|
20881
|
+
function precomputeGongmunList(blocks, gongmun) {
|
|
20882
|
+
const result = /* @__PURE__ */ new Map();
|
|
20883
|
+
let i = 0;
|
|
20884
|
+
while (i < blocks.length) {
|
|
20885
|
+
if (blocks[i].type !== "list_item") {
|
|
20886
|
+
i++;
|
|
20742
20887
|
continue;
|
|
20743
20888
|
}
|
|
20744
|
-
|
|
20745
|
-
|
|
20746
|
-
|
|
20747
|
-
|
|
20748
|
-
|
|
20749
|
-
|
|
20889
|
+
const run = [];
|
|
20890
|
+
while (i < blocks.length) {
|
|
20891
|
+
const t = blocks[i].type;
|
|
20892
|
+
if (t === "list_item") {
|
|
20893
|
+
run.push(i);
|
|
20894
|
+
i++;
|
|
20895
|
+
continue;
|
|
20750
20896
|
}
|
|
20751
|
-
|
|
20752
|
-
|
|
20753
|
-
|
|
20754
|
-
|
|
20755
|
-
|
|
20756
|
-
|
|
20757
|
-
|
|
20758
|
-
currentRow.push({ inner: raw.slice(cellStart, m.index), colSpan: cellInfo.colSpan, rowSpan: cellInfo.rowSpan });
|
|
20759
|
-
cellStart = -1;
|
|
20760
|
-
cellInfo = null;
|
|
20897
|
+
if (t === "table" || t === "html_table") {
|
|
20898
|
+
let j = i + 1;
|
|
20899
|
+
while (j < blocks.length && (blocks[j].type === "table" || blocks[j].type === "html_table")) j++;
|
|
20900
|
+
if (j < blocks.length && blocks[j].type === "list_item") {
|
|
20901
|
+
i = j;
|
|
20902
|
+
continue;
|
|
20903
|
+
}
|
|
20761
20904
|
}
|
|
20905
|
+
break;
|
|
20762
20906
|
}
|
|
20907
|
+
const depths = run.map((bi) => Math.min(Math.max(blocks[bi].indent || 0, 0), GONGMUN_LIST_LEVELS - 1));
|
|
20908
|
+
const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
|
|
20909
|
+
const numberer = new GongmunNumberer(gongmun.numbering);
|
|
20910
|
+
run.forEach((bi, k) => {
|
|
20911
|
+
const marker = numberer.next(depths[k], suppress[k]);
|
|
20912
|
+
result.set(bi, { marker, depth: depths[k] });
|
|
20913
|
+
});
|
|
20763
20914
|
}
|
|
20764
|
-
|
|
20765
|
-
return rows;
|
|
20915
|
+
return result;
|
|
20766
20916
|
}
|
|
20767
|
-
|
|
20768
|
-
|
|
20769
|
-
|
|
20770
|
-
|
|
20771
|
-
if (
|
|
20772
|
-
|
|
20773
|
-
|
|
20774
|
-
|
|
20775
|
-
if (/<img\s/i.test(work)) {
|
|
20776
|
-
hadNonText = true;
|
|
20777
|
-
work = work.replace(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi, "");
|
|
20778
|
-
}
|
|
20779
|
-
const lines = work.split(/<br\s*\/?>/gi).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
20780
|
-
return { lines, hadNonText };
|
|
20917
|
+
|
|
20918
|
+
// src/diff/text-diff.ts
|
|
20919
|
+
function similarity(a, b) {
|
|
20920
|
+
if (a === b) return 1;
|
|
20921
|
+
if (!a || !b) return 0;
|
|
20922
|
+
const maxLen = Math.max(a.length, b.length);
|
|
20923
|
+
if (maxLen === 0) return 1;
|
|
20924
|
+
return 1 - levenshtein(a, b) / maxLen;
|
|
20781
20925
|
}
|
|
20782
|
-
function
|
|
20783
|
-
|
|
20784
|
-
let depth = 0;
|
|
20785
|
-
let start = -1;
|
|
20786
|
-
const re = /<(\/?)table(?:[\s>]|>)/gi;
|
|
20787
|
-
let m;
|
|
20788
|
-
while ((m = re.exec(html)) !== null) {
|
|
20789
|
-
if (m[1] !== "/") {
|
|
20790
|
-
if (depth === 0) start = m.index;
|
|
20791
|
-
depth++;
|
|
20792
|
-
} else {
|
|
20793
|
-
depth--;
|
|
20794
|
-
if (depth === 0 && start >= 0) {
|
|
20795
|
-
result.push(html.slice(start, m.index + m[0].length));
|
|
20796
|
-
start = -1;
|
|
20797
|
-
}
|
|
20798
|
-
if (depth < 0) depth = 0;
|
|
20799
|
-
}
|
|
20800
|
-
}
|
|
20801
|
-
return result;
|
|
20926
|
+
function normalizedSimilarity(a, b) {
|
|
20927
|
+
return similarity(normalize(a), normalize(b));
|
|
20802
20928
|
}
|
|
20803
|
-
function
|
|
20804
|
-
|
|
20805
|
-
|
|
20806
|
-
|
|
20807
|
-
|
|
20808
|
-
|
|
20809
|
-
|
|
20810
|
-
|
|
20811
|
-
|
|
20812
|
-
|
|
20813
|
-
|
|
20814
|
-
|
|
20815
|
-
|
|
20816
|
-
|
|
20929
|
+
function normalize(s) {
|
|
20930
|
+
return s.replace(/\s+/g, " ").trim();
|
|
20931
|
+
}
|
|
20932
|
+
var MAX_LEVENSHTEIN_LEN = 1e4;
|
|
20933
|
+
function levenshtein(a, b) {
|
|
20934
|
+
if (a.length + b.length > MAX_LEVENSHTEIN_LEN) {
|
|
20935
|
+
const sampleLen = Math.min(500, a.length, b.length);
|
|
20936
|
+
let diffs = 0;
|
|
20937
|
+
for (let i = 0; i < sampleLen; i++) if (a[i] !== b[i]) diffs++;
|
|
20938
|
+
const sampleRate = sampleLen > 0 ? diffs / sampleLen : 1;
|
|
20939
|
+
return Math.abs(a.length - b.length) + Math.round(Math.min(a.length, b.length) * sampleRate);
|
|
20940
|
+
}
|
|
20941
|
+
if (a.length > b.length) [a, b] = [b, a];
|
|
20942
|
+
const m = a.length;
|
|
20943
|
+
const n = b.length;
|
|
20944
|
+
let prev = Array.from({ length: m + 1 }, (_, i) => i);
|
|
20945
|
+
let curr = new Array(m + 1);
|
|
20946
|
+
for (let j = 1; j <= n; j++) {
|
|
20947
|
+
curr[0] = j;
|
|
20948
|
+
for (let i = 1; i <= m; i++) {
|
|
20949
|
+
if (a[i - 1] === b[j - 1]) {
|
|
20950
|
+
curr[i] = prev[i - 1];
|
|
20951
|
+
} else {
|
|
20952
|
+
curr[i] = 1 + Math.min(prev[i - 1], prev[i], curr[i - 1]);
|
|
20953
|
+
}
|
|
20817
20954
|
}
|
|
20955
|
+
;
|
|
20956
|
+
[prev, curr] = [curr, prev];
|
|
20818
20957
|
}
|
|
20819
|
-
|
|
20820
|
-
return result;
|
|
20958
|
+
return prev[m];
|
|
20821
20959
|
}
|
|
20822
20960
|
|
|
20823
|
-
// src/
|
|
20824
|
-
|
|
20825
|
-
var NS_PARA = "http://www.hancom.co.kr/hwpml/2011/paragraph";
|
|
20826
|
-
var NS_HEAD = "http://www.hancom.co.kr/hwpml/2011/head";
|
|
20827
|
-
var NS_CORE = "http://www.hancom.co.kr/hwpml/2011/core";
|
|
20828
|
-
var NS_OPF = "http://www.idpf.org/2007/opf/";
|
|
20829
|
-
var NS_HPF = "http://www.hancom.co.kr/schema/2011/hpf";
|
|
20830
|
-
var NS_OCF = "urn:oasis:names:tc:opendocument:xmlns:container";
|
|
20831
|
-
var CHAR_NORMAL = 0;
|
|
20832
|
-
var CHAR_BOLD = 1;
|
|
20833
|
-
var CHAR_ITALIC = 2;
|
|
20834
|
-
var CHAR_BOLD_ITALIC = 3;
|
|
20835
|
-
var CHAR_CODE = 4;
|
|
20836
|
-
var CHAR_H1 = 5;
|
|
20837
|
-
var CHAR_H2 = 6;
|
|
20838
|
-
var CHAR_H3 = 7;
|
|
20839
|
-
var CHAR_H4 = 8;
|
|
20840
|
-
var CHAR_TABLE_HEADER = 9;
|
|
20841
|
-
var CHAR_QUOTE = 10;
|
|
20842
|
-
var PARA_NORMAL = 0;
|
|
20843
|
-
var PARA_H1 = 1;
|
|
20844
|
-
var PARA_H2 = 2;
|
|
20845
|
-
var PARA_H3 = 3;
|
|
20846
|
-
var PARA_H4 = 4;
|
|
20847
|
-
var PARA_CODE = 5;
|
|
20848
|
-
var PARA_QUOTE = 6;
|
|
20849
|
-
var PARA_LIST = 7;
|
|
20850
|
-
var DEFAULT_TEXT_COLOR = "#000000";
|
|
20851
|
-
function resolveTheme(theme) {
|
|
20852
|
-
return {
|
|
20853
|
-
h1: theme?.headingColors?.[1] ?? DEFAULT_TEXT_COLOR,
|
|
20854
|
-
h2: theme?.headingColors?.[2] ?? DEFAULT_TEXT_COLOR,
|
|
20855
|
-
h3: theme?.headingColors?.[3] ?? DEFAULT_TEXT_COLOR,
|
|
20856
|
-
h4: theme?.headingColors?.[4] ?? theme?.headingColors?.[3] ?? DEFAULT_TEXT_COLOR,
|
|
20857
|
-
body: theme?.bodyColor ?? DEFAULT_TEXT_COLOR,
|
|
20858
|
-
quote: theme?.quoteColor ?? DEFAULT_TEXT_COLOR,
|
|
20859
|
-
/** quoteColor가 명시되었는지 — blockquote charPr 분기에 사용 (baseline 호환) */
|
|
20860
|
-
hasQuoteOption: theme?.quoteColor !== void 0,
|
|
20861
|
-
tableHeader: theme?.tableHeaderColor ?? theme?.bodyColor ?? DEFAULT_TEXT_COLOR,
|
|
20862
|
-
tableHeaderBold: !!theme?.tableHeaderBold
|
|
20863
|
-
};
|
|
20864
|
-
}
|
|
20865
|
-
async function markdownToHwpx(markdown, options) {
|
|
20866
|
-
const theme = resolveTheme(options?.theme);
|
|
20867
|
-
const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
|
|
20868
|
-
const blocks = parseMarkdownToBlocks(markdown);
|
|
20869
|
-
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
20870
|
-
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
20871
|
-
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit);
|
|
20872
|
-
const zip = new JSZip6();
|
|
20873
|
-
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
20874
|
-
zip.file("META-INF/container.xml", generateContainerXml());
|
|
20875
|
-
zip.file("Contents/content.hpf", generateManifest());
|
|
20876
|
-
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? []));
|
|
20877
|
-
zip.file("Contents/section0.xml", sectionXml);
|
|
20878
|
-
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
20879
|
-
return await zip.generateAsync({ type: "arraybuffer" });
|
|
20880
|
-
}
|
|
20881
|
-
function buildPrvText(blocks) {
|
|
20882
|
-
const lines = [];
|
|
20883
|
-
let bytes = 0;
|
|
20884
|
-
for (const b of blocks) {
|
|
20885
|
-
let text = b.text || (b.rows ? b.rows.map((r) => r.join(" ")).join("\n") : "");
|
|
20886
|
-
if (b.type === "html_table") text = text.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
20887
|
-
if (!text) continue;
|
|
20888
|
-
lines.push(text);
|
|
20889
|
-
bytes += text.length * 3;
|
|
20890
|
-
if (bytes > 1024) break;
|
|
20891
|
-
}
|
|
20892
|
-
return lines.join("\n").slice(0, 1024);
|
|
20893
|
-
}
|
|
20894
|
-
function parseMarkdownToBlocks(md2) {
|
|
20961
|
+
// src/roundtrip/markdown-units.ts
|
|
20962
|
+
function splitMarkdownUnits(md2) {
|
|
20895
20963
|
const lines = md2.split("\n");
|
|
20896
|
-
const
|
|
20964
|
+
const units = [];
|
|
20897
20965
|
let i = 0;
|
|
20898
20966
|
while (i < lines.length) {
|
|
20899
20967
|
const line = lines[i];
|
|
@@ -20901,420 +20969,369 @@ function parseMarkdownToBlocks(md2) {
|
|
|
20901
20969
|
i++;
|
|
20902
20970
|
continue;
|
|
20903
20971
|
}
|
|
20904
|
-
|
|
20905
|
-
|
|
20906
|
-
const fence = fenceMatch[1];
|
|
20907
|
-
const lang = fenceMatch[2].trim();
|
|
20908
|
-
const codeLines = [];
|
|
20909
|
-
i++;
|
|
20910
|
-
while (i < lines.length && !lines[i].startsWith(fence)) {
|
|
20911
|
-
codeLines.push(lines[i]);
|
|
20912
|
-
i++;
|
|
20913
|
-
}
|
|
20914
|
-
if (i < lines.length) i++;
|
|
20915
|
-
blocks.push({ type: "code_block", text: codeLines.join("\n"), lang });
|
|
20916
|
-
continue;
|
|
20917
|
-
}
|
|
20918
|
-
if (/^(\*{3,}|-{3,}|_{3,})\s*$/.test(line.trim())) {
|
|
20919
|
-
blocks.push({ type: "hr" });
|
|
20920
|
-
i++;
|
|
20921
|
-
continue;
|
|
20922
|
-
}
|
|
20923
|
-
const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
20924
|
-
if (headingMatch) {
|
|
20925
|
-
blocks.push({ type: "heading", text: headingMatch[2].trim(), level: headingMatch[1].length });
|
|
20926
|
-
i++;
|
|
20927
|
-
continue;
|
|
20928
|
-
}
|
|
20929
|
-
if (/^<table[\s>]/i.test(line.trimStart())) {
|
|
20930
|
-
const htmlLines = [];
|
|
20972
|
+
if (line.trim().startsWith("<table>")) {
|
|
20973
|
+
const collected2 = [];
|
|
20931
20974
|
let depth = 0;
|
|
20932
20975
|
while (i < lines.length) {
|
|
20933
20976
|
const l = lines[i];
|
|
20934
|
-
|
|
20935
|
-
depth += (l.match(/<table
|
|
20936
|
-
depth -= (l.match(/<\/table>/
|
|
20977
|
+
collected2.push(l);
|
|
20978
|
+
depth += (l.match(/<table>/g) || []).length;
|
|
20979
|
+
depth -= (l.match(/<\/table>/g) || []).length;
|
|
20937
20980
|
i++;
|
|
20938
20981
|
if (depth <= 0) break;
|
|
20939
20982
|
}
|
|
20940
|
-
|
|
20983
|
+
units.push({ kind: "html-table", raw: collected2.join("\n"), lines: collected2 });
|
|
20941
20984
|
continue;
|
|
20942
20985
|
}
|
|
20943
20986
|
if (line.trimStart().startsWith("|")) {
|
|
20944
|
-
const
|
|
20987
|
+
const collected2 = [];
|
|
20945
20988
|
while (i < lines.length && lines[i].trimStart().startsWith("|")) {
|
|
20946
|
-
|
|
20947
|
-
if (/^[\s|:\-]+$/.test(row)) {
|
|
20948
|
-
i++;
|
|
20949
|
-
continue;
|
|
20950
|
-
}
|
|
20951
|
-
const cells = row.split("|").slice(1, -1).map((c) => c.trim());
|
|
20952
|
-
if (cells.length > 0) tableRows.push(cells);
|
|
20989
|
+
collected2.push(lines[i]);
|
|
20953
20990
|
i++;
|
|
20954
20991
|
}
|
|
20955
|
-
|
|
20992
|
+
units.push({ kind: "gfm-table", raw: collected2.join("\n"), lines: collected2 });
|
|
20956
20993
|
continue;
|
|
20957
20994
|
}
|
|
20958
|
-
if (line.
|
|
20959
|
-
|
|
20960
|
-
|
|
20961
|
-
quoteLines.push(lines[i].replace(/^>\s?/, ""));
|
|
20962
|
-
i++;
|
|
20963
|
-
}
|
|
20964
|
-
for (const ql of quoteLines) {
|
|
20965
|
-
blocks.push({ type: "blockquote", text: ql.trim() || "" });
|
|
20966
|
-
}
|
|
20995
|
+
if (/^-{3,}\s*$/.test(line.trim())) {
|
|
20996
|
+
units.push({ kind: "separator", raw: line.trim(), lines: [line.trim()] });
|
|
20997
|
+
i++;
|
|
20967
20998
|
continue;
|
|
20968
20999
|
}
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
const indent = Math.floor(listMatch[1].length / 2);
|
|
20972
|
-
const ordered = /\d/.test(listMatch[2]);
|
|
20973
|
-
blocks.push({ type: "list_item", text: listMatch[3].trim(), ordered, indent });
|
|
21000
|
+
if (/^!\[image\]\([^)]*\)\s*$/.test(line.trim())) {
|
|
21001
|
+
units.push({ kind: "image", raw: line.trim(), lines: [line.trim()] });
|
|
20974
21002
|
i++;
|
|
20975
21003
|
continue;
|
|
20976
21004
|
}
|
|
20977
|
-
|
|
20978
|
-
i
|
|
21005
|
+
const collected = [];
|
|
21006
|
+
while (i < lines.length && lines[i].trim() && !lines[i].trimStart().startsWith("|") && !lines[i].trim().startsWith("<table>")) {
|
|
21007
|
+
collected.push(lines[i].trim());
|
|
21008
|
+
i++;
|
|
21009
|
+
}
|
|
21010
|
+
units.push({ kind: "text", raw: collected.join("\n"), lines: collected });
|
|
20979
21011
|
}
|
|
20980
|
-
return
|
|
21012
|
+
return units;
|
|
20981
21013
|
}
|
|
20982
|
-
function
|
|
20983
|
-
|
|
20984
|
-
|
|
20985
|
-
|
|
20986
|
-
|
|
20987
|
-
|
|
20988
|
-
|
|
20989
|
-
|
|
20990
|
-
const idx = match.index;
|
|
20991
|
-
if (idx > lastIdx) {
|
|
20992
|
-
spans.push({ text: text.slice(lastIdx, idx), bold: false, italic: false, code: false });
|
|
21014
|
+
function alignUnits(a, b) {
|
|
21015
|
+
const m = a.length, n = b.length;
|
|
21016
|
+
if (m * n > 4e6) {
|
|
21017
|
+
const result2 = [];
|
|
21018
|
+
let pre = 0;
|
|
21019
|
+
while (pre < m && pre < n && a[pre] === b[pre]) {
|
|
21020
|
+
result2.push([pre, pre]);
|
|
21021
|
+
pre++;
|
|
20993
21022
|
}
|
|
20994
|
-
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
} else if (raw.startsWith("**") || raw.startsWith("__")) {
|
|
21000
|
-
spans.push({ text: raw.slice(2, -2), bold: true, italic: false, code: false });
|
|
21023
|
+
let suf = 0;
|
|
21024
|
+
while (suf < m - pre && suf < n - pre && a[m - 1 - suf] === b[n - 1 - suf]) suf++;
|
|
21025
|
+
const aMid = m - pre - suf, bMid = n - pre - suf;
|
|
21026
|
+
if (aMid === bMid) {
|
|
21027
|
+
for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, pre + i2]);
|
|
21001
21028
|
} else {
|
|
21002
|
-
|
|
21029
|
+
for (let i2 = 0; i2 < aMid; i2++) result2.push([pre + i2, null]);
|
|
21030
|
+
for (let j2 = 0; j2 < bMid; j2++) result2.push([null, pre + j2]);
|
|
21003
21031
|
}
|
|
21004
|
-
|
|
21032
|
+
for (let s = suf - 1; s >= 0; s--) result2.push([m - 1 - s, n - 1 - s]);
|
|
21033
|
+
return result2;
|
|
21005
21034
|
}
|
|
21006
|
-
|
|
21007
|
-
|
|
21035
|
+
const dp = Array.from({ length: m + 1 }, () => new Int32Array(n + 1));
|
|
21036
|
+
for (let i2 = 1; i2 <= m; i2++) {
|
|
21037
|
+
for (let j2 = 1; j2 <= n; j2++) {
|
|
21038
|
+
dp[i2][j2] = a[i2 - 1] === b[j2 - 1] ? dp[i2 - 1][j2 - 1] + 1 : Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
21039
|
+
}
|
|
21008
21040
|
}
|
|
21009
|
-
|
|
21010
|
-
|
|
21041
|
+
const matches = [];
|
|
21042
|
+
let i = m, j = n;
|
|
21043
|
+
while (i > 0 && j > 0) {
|
|
21044
|
+
if (a[i - 1] === b[j - 1] && dp[i][j] === dp[i - 1][j - 1] + 1) {
|
|
21045
|
+
matches.push([i - 1, j - 1]);
|
|
21046
|
+
i--;
|
|
21047
|
+
j--;
|
|
21048
|
+
} else if (dp[i - 1][j] >= dp[i][j - 1]) i--;
|
|
21049
|
+
else j--;
|
|
21011
21050
|
}
|
|
21012
|
-
|
|
21013
|
-
|
|
21014
|
-
|
|
21015
|
-
|
|
21016
|
-
|
|
21017
|
-
|
|
21018
|
-
|
|
21019
|
-
|
|
21051
|
+
matches.reverse();
|
|
21052
|
+
const result = [];
|
|
21053
|
+
let ai = 0, bi = 0;
|
|
21054
|
+
const flushGap = (aEnd, bEnd) => {
|
|
21055
|
+
if (aEnd - ai === bEnd - bi) {
|
|
21056
|
+
while (ai < aEnd) result.push([ai++, bi++]);
|
|
21057
|
+
return;
|
|
21058
|
+
}
|
|
21059
|
+
while (ai < aEnd && bi < bEnd) {
|
|
21060
|
+
const sim = normalizedSimilarity(a[ai], b[bi]);
|
|
21061
|
+
if (sim >= 0.4) {
|
|
21062
|
+
if (aEnd - ai > bEnd - bi && bestSimInRange(a, ai + 1, ai + (aEnd - ai) - (bEnd - bi), b[bi]) > sim) {
|
|
21063
|
+
result.push([ai++, null]);
|
|
21064
|
+
} else if (bEnd - bi > aEnd - ai && bestSimInRange(b, bi + 1, bi + (bEnd - bi) - (aEnd - ai), a[ai]) > sim) {
|
|
21065
|
+
result.push([null, bi++]);
|
|
21066
|
+
} else {
|
|
21067
|
+
result.push([ai++, bi++]);
|
|
21068
|
+
}
|
|
21069
|
+
} else if (aEnd - ai >= bEnd - bi) result.push([ai++, null]);
|
|
21070
|
+
else result.push([null, bi++]);
|
|
21071
|
+
}
|
|
21072
|
+
while (ai < aEnd) result.push([ai++, null]);
|
|
21073
|
+
while (bi < bEnd) result.push([null, bi++]);
|
|
21074
|
+
};
|
|
21075
|
+
for (const [pi, pj] of matches) {
|
|
21076
|
+
flushGap(pi, pj);
|
|
21077
|
+
result.push([ai++, bi++]);
|
|
21078
|
+
}
|
|
21079
|
+
flushGap(m, n);
|
|
21080
|
+
return result;
|
|
21020
21081
|
}
|
|
21021
|
-
function
|
|
21022
|
-
|
|
21082
|
+
function bestSimInRange(arr, from, to, target) {
|
|
21083
|
+
let best = 0;
|
|
21084
|
+
for (let k = from; k <= to && k < arr.length; k++) {
|
|
21085
|
+
const s = normalizedSimilarity(arr[k], target);
|
|
21086
|
+
if (s > best) best = s;
|
|
21087
|
+
}
|
|
21088
|
+
return best;
|
|
21023
21089
|
}
|
|
21024
|
-
function
|
|
21025
|
-
|
|
21026
|
-
return spans.map((span) => {
|
|
21027
|
-
let charId = span.code || span.bold || span.italic ? spanToCharPrId(span) : defaultCharPr;
|
|
21028
|
-
if (mapCharId) charId = mapCharId(charId);
|
|
21029
|
-
return `<hp:run charPrIDRef="${charId}"><hp:t>${escapeXml(span.text)}</hp:t></hp:run>`;
|
|
21030
|
-
}).join("");
|
|
21090
|
+
function escapeGfm(text) {
|
|
21091
|
+
return text.replace(/~/g, "\\~");
|
|
21031
21092
|
}
|
|
21032
|
-
|
|
21033
|
-
|
|
21034
|
-
|
|
21093
|
+
var HWP_SHAPE_ALT_TEXT_RE = /(?:모서리가 둥근 |둥근 )?(?:사각형|직사각형|정사각형|원|타원|삼각형|이등변 삼각형|직각 삼각형|선|직선|곡선|화살표|굵은 화살표|이중 화살표|오각형|육각형|팔각형|별|[4-8]점별|십자|십자형|구름|구름형|마름모|도넛|평행사변형|사다리꼴|부채꼴|호|반원|물결|번개|하트|빗금|블록 화살표|수식|표|그림|개체|그리기\s?개체|묶음\s?개체|글상자|수식\s?개체|OLE\s?개체)\s?입니다\.?/g;
|
|
21094
|
+
function sanitizeText(text) {
|
|
21095
|
+
let result = mapPuaText(text).replace(/[\u{F0000}-\u{FFFFD}]/gu, "").replace(HWP_SHAPE_ALT_TEXT_RE, "").replace(/ +/g, " ").trim();
|
|
21096
|
+
if (result.length <= 30 && result.includes(" ")) {
|
|
21097
|
+
const tokens = result.split(" ");
|
|
21098
|
+
const koreanSingleCharCount = tokens.filter((t) => t.length === 1 && /[가-ㄱ-ㆎ]/.test(t)).length;
|
|
21099
|
+
if (tokens.length >= 3 && koreanSingleCharCount / tokens.length >= 0.7) {
|
|
21100
|
+
result = tokens.join("");
|
|
21101
|
+
}
|
|
21035
21102
|
}
|
|
21036
|
-
|
|
21037
|
-
return `<hp:p paraPrIDRef="${paraPrId}" styleIDRef="0">${runs}</hp:p>`;
|
|
21038
|
-
}
|
|
21039
|
-
function headingParaPrId(level) {
|
|
21040
|
-
if (level === 1) return PARA_H1;
|
|
21041
|
-
if (level === 2) return PARA_H2;
|
|
21042
|
-
if (level === 3) return PARA_H3;
|
|
21043
|
-
return PARA_H4;
|
|
21103
|
+
return result;
|
|
21044
21104
|
}
|
|
21045
|
-
function
|
|
21046
|
-
|
|
21047
|
-
if (level === 2) return CHAR_H2;
|
|
21048
|
-
if (level === 3) return CHAR_H3;
|
|
21049
|
-
return CHAR_H4;
|
|
21105
|
+
function normForMatch(text) {
|
|
21106
|
+
return sanitizeText(text).replace(/\s+/g, " ").trim();
|
|
21050
21107
|
}
|
|
21051
|
-
function
|
|
21052
|
-
return
|
|
21053
|
-
<ocf:container xmlns:ocf="${NS_OCF}" xmlns:hpf="${NS_HPF}">
|
|
21054
|
-
<ocf:rootfiles>
|
|
21055
|
-
<ocf:rootfile full-path="Contents/content.hpf" media-type="application/hwpml-package+xml"/>
|
|
21056
|
-
</ocf:rootfiles>
|
|
21057
|
-
</ocf:container>`;
|
|
21108
|
+
function unescapeGfm(text) {
|
|
21109
|
+
return text.replace(/\\~/g, "~");
|
|
21058
21110
|
}
|
|
21059
|
-
function
|
|
21060
|
-
|
|
21061
|
-
|
|
21062
|
-
<opf:manifest>
|
|
21063
|
-
<opf:item id="header" href="Contents/header.xml" media-type="application/xml"/>
|
|
21064
|
-
<opf:item id="section0" href="Contents/section0.xml" media-type="application/xml"/>
|
|
21065
|
-
</opf:manifest>
|
|
21066
|
-
<opf:spine>
|
|
21067
|
-
<opf:itemref idref="header" linear="no"/>
|
|
21068
|
-
<opf:itemref idref="section0" linear="yes"/>
|
|
21069
|
-
</opf:spine>
|
|
21070
|
-
</opf:package>`;
|
|
21111
|
+
function summarize(text) {
|
|
21112
|
+
const t = text.replace(/\s+/g, " ").trim();
|
|
21113
|
+
return t.length > 80 ? t.slice(0, 77) + "..." : t;
|
|
21071
21114
|
}
|
|
21072
|
-
function
|
|
21073
|
-
const
|
|
21074
|
-
|
|
21075
|
-
|
|
21076
|
-
|
|
21077
|
-
|
|
21078
|
-
|
|
21079
|
-
|
|
21080
|
-
|
|
21081
|
-
|
|
21082
|
-
|
|
21115
|
+
function replicateGfmTable(table) {
|
|
21116
|
+
const { cells, rows: numRows, cols: numCols } = table;
|
|
21117
|
+
if (numRows === 0 || numCols === 0) return null;
|
|
21118
|
+
if (numRows === 1 && numCols === 1) return null;
|
|
21119
|
+
if (numCols === 1) return null;
|
|
21120
|
+
const display = Array.from({ length: numRows }, (_, r) => Array.from({ length: numCols }, (_2, c) => ({ text: "", gridR: r, gridC: c })));
|
|
21121
|
+
const skip = /* @__PURE__ */ new Set();
|
|
21122
|
+
for (let r = 0; r < numRows; r++) {
|
|
21123
|
+
for (let c = 0; c < numCols; c++) {
|
|
21124
|
+
if (skip.has(`${r},${c}`)) continue;
|
|
21125
|
+
const cell = cells[r]?.[c];
|
|
21126
|
+
if (!cell) continue;
|
|
21127
|
+
display[r][c] = {
|
|
21128
|
+
text: escapeGfm(sanitizeText(cell.text)).replace(/\|/g, "\\|").replace(/\n/g, "<br>"),
|
|
21129
|
+
gridR: r,
|
|
21130
|
+
gridC: c
|
|
21131
|
+
};
|
|
21132
|
+
for (let dr = 0; dr < cell.rowSpan; dr++) {
|
|
21133
|
+
for (let dc = 0; dc < cell.colSpan; dc++) {
|
|
21134
|
+
if (dr === 0 && dc === 0) continue;
|
|
21135
|
+
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
21136
|
+
}
|
|
21137
|
+
}
|
|
21138
|
+
c += cell.colSpan - 1;
|
|
21139
|
+
}
|
|
21140
|
+
}
|
|
21141
|
+
const uniqueRows = [];
|
|
21142
|
+
let pendingLabelRow = null;
|
|
21143
|
+
for (let r = 0; r < display.length; r++) {
|
|
21144
|
+
const row = display[r];
|
|
21145
|
+
if (row.every((cell) => cell.text === "")) continue;
|
|
21146
|
+
const nonEmptyCols = row.filter((cell) => cell.text !== "");
|
|
21147
|
+
const hasSkipInRow = row.some((_, c) => skip.has(`${r},${c}`));
|
|
21148
|
+
if (!hasSkipInRow && nonEmptyCols.length === 1 && row[0].text !== "" && row.slice(1).every((c) => c.text === "")) {
|
|
21149
|
+
if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
|
|
21150
|
+
pendingLabelRow = row;
|
|
21151
|
+
continue;
|
|
21152
|
+
}
|
|
21153
|
+
if (pendingLabelRow) {
|
|
21154
|
+
if (row[0].text === "") row[0] = pendingLabelRow[0];
|
|
21155
|
+
else uniqueRows.push(pendingLabelRow);
|
|
21156
|
+
pendingLabelRow = null;
|
|
21157
|
+
}
|
|
21158
|
+
uniqueRows.push(row);
|
|
21159
|
+
}
|
|
21160
|
+
if (pendingLabelRow) uniqueRows.push(pendingLabelRow);
|
|
21161
|
+
return uniqueRows.length > 0 ? uniqueRows : null;
|
|
21083
21162
|
}
|
|
21084
|
-
function
|
|
21085
|
-
const
|
|
21086
|
-
const
|
|
21087
|
-
|
|
21088
|
-
|
|
21089
|
-
|
|
21090
|
-
|
|
21091
|
-
|
|
21092
|
-
|
|
21093
|
-
|
|
21094
|
-
|
|
21095
|
-
<hh:border borderFillIDRef="1" offsetLeft="0" offsetRight="0" offsetTop="0" offsetBottom="0" connect="0" ignoreMargin="0"/>
|
|
21096
|
-
</hh:paraPr>`;
|
|
21163
|
+
function parseGfmTable(lines) {
|
|
21164
|
+
const rows = [];
|
|
21165
|
+
for (const line of lines) {
|
|
21166
|
+
const trimmed = line.trim();
|
|
21167
|
+
if (!trimmed.startsWith("|")) continue;
|
|
21168
|
+
const cells = trimmed.split(/(?<!\\)\|/).slice(1, -1).map((c) => c.trim());
|
|
21169
|
+
if (cells.length === 0) continue;
|
|
21170
|
+
if (cells.every((c) => /^:?-{3,}:?$/.test(c))) continue;
|
|
21171
|
+
rows.push(cells);
|
|
21172
|
+
}
|
|
21173
|
+
return rows;
|
|
21097
21174
|
}
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
var GONGMUN_CENTER = GONGMUN_LIST_BASE + GONGMUN_LIST_LEVELS;
|
|
21101
|
-
var CHAR_VARIANT_BASE = 11;
|
|
21102
|
-
var GONGMUN_BODY_RATIO = 95;
|
|
21103
|
-
function plainRenderText(text) {
|
|
21104
|
-
return parseInlineMarkdown(text).map((s) => s.text).join("");
|
|
21175
|
+
function unescapeGfmCell(text) {
|
|
21176
|
+
return text.replace(/<br\s*\/?>/gi, "\n").replace(/\\\|/g, "|").replace(/\\~/g, "~");
|
|
21105
21177
|
}
|
|
21106
|
-
function
|
|
21107
|
-
|
|
21108
|
-
|
|
21109
|
-
|
|
21110
|
-
|
|
21111
|
-
|
|
21112
|
-
|
|
21113
|
-
|
|
21114
|
-
|
|
21115
|
-
|
|
21116
|
-
|
|
21117
|
-
if (block.type === "list_item" && gongmunList.has(i)) {
|
|
21118
|
-
const { marker, depth } = gongmunList.get(i);
|
|
21119
|
-
const content = plainRenderText(block.text || "");
|
|
21120
|
-
text = marker ? `${marker} ${content}` : content;
|
|
21121
|
-
const { left, indent } = levelIndent(depth, gongmun.bodyHeight, gongmun.numbering);
|
|
21122
|
-
firstW = pageW - left - Math.max(indent, 0);
|
|
21123
|
-
contW = pageW - left - Math.max(-indent, 0);
|
|
21124
|
-
} else if (block.type === "paragraph") {
|
|
21125
|
-
const raw = (block.text || "").trim();
|
|
21126
|
-
if (/^<center>[\s\S]*<\/center>$/i.test(raw)) continue;
|
|
21127
|
-
text = plainRenderText(raw);
|
|
21128
|
-
firstW = contW = pageW;
|
|
21129
|
-
} else {
|
|
21130
|
-
continue;
|
|
21131
|
-
}
|
|
21132
|
-
if (!text) continue;
|
|
21133
|
-
const r = fitRatioForFewerLines(text, firstW, contW, gongmun.bodyHeight, GONGMUN_BODY_RATIO, minRatio);
|
|
21134
|
-
if (r === null) continue;
|
|
21135
|
-
ratioByBlock.set(i, r);
|
|
21136
|
-
if (!variants.includes(r)) variants.push(r);
|
|
21178
|
+
function replicateCellInnerHtml(cell) {
|
|
21179
|
+
if (cell.blocks?.length) {
|
|
21180
|
+
return cell.blocks.map((b) => {
|
|
21181
|
+
if (b.type === "table" && b.table) {
|
|
21182
|
+
const cap = b.table.caption ? sanitizeText(b.table.caption) : "";
|
|
21183
|
+
return (cap ? cap + "<br>" : "") + replicateTableToHtml(b.table);
|
|
21184
|
+
}
|
|
21185
|
+
if (b.type === "image" && b.text) return `<img src="${b.text}" alt="image">`;
|
|
21186
|
+
const t = sanitizeText(b.text ?? "");
|
|
21187
|
+
return t ? t.replace(/\n/g, "<br>") : "";
|
|
21188
|
+
}).filter(Boolean).join("<br>");
|
|
21137
21189
|
}
|
|
21138
|
-
return
|
|
21190
|
+
return sanitizeText(cell.text).replace(/\n/g, "<br>");
|
|
21139
21191
|
}
|
|
21140
|
-
function
|
|
21141
|
-
const
|
|
21142
|
-
|
|
21143
|
-
|
|
21144
|
-
|
|
21192
|
+
function replicateTableToHtml(table) {
|
|
21193
|
+
const rows = replicateHtmlTable(table);
|
|
21194
|
+
const lines = ["<table>"];
|
|
21195
|
+
for (let r = 0; r < rows.length; r++) {
|
|
21196
|
+
const tag = rows[r].tag;
|
|
21197
|
+
const rowHtml = rows[r].cells.map((cell) => {
|
|
21198
|
+
const attrs = [];
|
|
21199
|
+
if (cell.colSpan > 1) attrs.push(`colspan="${cell.colSpan}"`);
|
|
21200
|
+
if (cell.rowSpan > 1) attrs.push(`rowspan="${cell.rowSpan}"`);
|
|
21201
|
+
const attrStr = attrs.length ? " " + attrs.join(" ") : "";
|
|
21202
|
+
return `<${tag}${attrStr}>${cell.inner}</${tag}>`;
|
|
21203
|
+
});
|
|
21204
|
+
if (rowHtml.length) lines.push(`<tr>${rowHtml.join("")}</tr>`);
|
|
21205
|
+
}
|
|
21206
|
+
lines.push("</table>");
|
|
21207
|
+
return lines.join("\n");
|
|
21145
21208
|
}
|
|
21146
|
-
function
|
|
21147
|
-
|
|
21148
|
-
|
|
21149
|
-
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
|
|
21154
|
-
|
|
21209
|
+
function replicateHtmlTable(table) {
|
|
21210
|
+
const { cells, rows: numRows, cols: numCols } = table;
|
|
21211
|
+
const skip = /* @__PURE__ */ new Set();
|
|
21212
|
+
const result = [];
|
|
21213
|
+
for (let r = 0; r < numRows; r++) {
|
|
21214
|
+
const tag = r === 0 ? "th" : "td";
|
|
21215
|
+
const rowCells = [];
|
|
21216
|
+
for (let c = 0; c < numCols; c++) {
|
|
21217
|
+
if (skip.has(`${r},${c}`)) continue;
|
|
21218
|
+
const cell = cells[r]?.[c];
|
|
21219
|
+
if (!cell) continue;
|
|
21220
|
+
for (let dr = 0; dr < cell.rowSpan; dr++) {
|
|
21221
|
+
for (let dc = 0; dc < cell.colSpan; dc++) {
|
|
21222
|
+
if (dr === 0 && dc === 0) continue;
|
|
21223
|
+
if (r + dr < numRows && c + dc < numCols) skip.add(`${r + dr},${c + dc}`);
|
|
21224
|
+
}
|
|
21225
|
+
}
|
|
21226
|
+
rowCells.push({
|
|
21227
|
+
inner: replicateCellInnerHtml(cell),
|
|
21228
|
+
colSpan: cell.colSpan,
|
|
21229
|
+
rowSpan: cell.rowSpan,
|
|
21230
|
+
gridR: r,
|
|
21231
|
+
gridC: c
|
|
21232
|
+
});
|
|
21233
|
+
}
|
|
21234
|
+
if (rowCells.length) result.push({ tag, cells: rowCells });
|
|
21155
21235
|
}
|
|
21156
|
-
|
|
21157
|
-
|
|
21158
|
-
|
|
21159
|
-
|
|
21160
|
-
|
|
21161
|
-
|
|
21162
|
-
|
|
21163
|
-
|
|
21164
|
-
|
|
21165
|
-
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
|
|
21170
|
-
|
|
21171
|
-
|
|
21172
|
-
|
|
21173
|
-
|
|
21174
|
-
|
|
21175
|
-
|
|
21176
|
-
)
|
|
21236
|
+
return result;
|
|
21237
|
+
}
|
|
21238
|
+
function parseHtmlTable(raw) {
|
|
21239
|
+
const re = /<(\/?)(table|tr|td|th)((?:"[^"]*"|'[^']*'|[^>"'])*?)>/gi;
|
|
21240
|
+
let depth = 0;
|
|
21241
|
+
let currentRow = null;
|
|
21242
|
+
let cellStart = -1;
|
|
21243
|
+
let cellInfo = null;
|
|
21244
|
+
const rows = [];
|
|
21245
|
+
let m;
|
|
21246
|
+
while ((m = re.exec(raw)) !== null) {
|
|
21247
|
+
const isClose = m[1] === "/";
|
|
21248
|
+
const tag = m[2].toLowerCase();
|
|
21249
|
+
const attrs = m[3] || "";
|
|
21250
|
+
if (tag === "table") {
|
|
21251
|
+
depth += isClose ? -1 : 1;
|
|
21252
|
+
if (depth < 0) return null;
|
|
21253
|
+
continue;
|
|
21254
|
+
}
|
|
21255
|
+
if (depth !== 1) continue;
|
|
21256
|
+
if (tag === "tr") {
|
|
21257
|
+
if (!isClose) currentRow = [];
|
|
21258
|
+
else if (currentRow) {
|
|
21259
|
+
rows.push({ tag: rows.length === 0 ? "th" : "td", cells: currentRow });
|
|
21260
|
+
currentRow = null;
|
|
21261
|
+
}
|
|
21262
|
+
} else {
|
|
21263
|
+
if (!isClose) {
|
|
21264
|
+
const cs = parseInt(attrs.match(/colspan\s*=\s*"(\d+)"/i)?.[1] || "1", 10);
|
|
21265
|
+
const rs = parseInt(attrs.match(/rowspan\s*=\s*"(\d+)"/i)?.[1] || "1", 10);
|
|
21266
|
+
cellStart = m.index + m[0].length;
|
|
21267
|
+
cellInfo = { colSpan: isNaN(cs) ? 1 : cs, rowSpan: isNaN(rs) ? 1 : rs };
|
|
21268
|
+
} else if (cellStart >= 0 && cellInfo && currentRow) {
|
|
21269
|
+
currentRow.push({ inner: raw.slice(cellStart, m.index), colSpan: cellInfo.colSpan, rowSpan: cellInfo.rowSpan });
|
|
21270
|
+
cellStart = -1;
|
|
21271
|
+
cellInfo = null;
|
|
21272
|
+
}
|
|
21273
|
+
}
|
|
21177
21274
|
}
|
|
21178
|
-
return
|
|
21179
|
-
|
|
21180
|
-
</hh:charProperties>`;
|
|
21275
|
+
if (depth !== 0) return null;
|
|
21276
|
+
return rows;
|
|
21181
21277
|
}
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
|
|
21185
|
-
|
|
21186
|
-
|
|
21187
|
-
|
|
21188
|
-
|
|
21189
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: 160 }),
|
|
21190
|
-
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400 }),
|
|
21191
|
-
paraPr(6, { align: "LEFT", lineSpacing: 150, indent: 600 }),
|
|
21192
|
-
paraPr(7, { align: "LEFT", lineSpacing: 160, indent: 600 })
|
|
21193
|
-
];
|
|
21194
|
-
return `<hh:paraProperties itemCnt="${base2.length}">
|
|
21195
|
-
${base2.join("\n")}
|
|
21196
|
-
</hh:paraProperties>`;
|
|
21278
|
+
var AUTONUM_PREFIX_RE = /^(?:[0-90-9a-zA-Z가-힣]{1,6}[.)\]:]|[([][0-90-9a-zA-Z가-힣]{1,6}[)\]][.:]?|[ⅰ-ⅹⅠ-Ⅹ①-⑮][.)\]:]?)$/u;
|
|
21279
|
+
function htmlCellInnerToLines(inner) {
|
|
21280
|
+
let hadNonText = false;
|
|
21281
|
+
let work = inner;
|
|
21282
|
+
if (/<table[\s>]/i.test(work)) {
|
|
21283
|
+
hadNonText = true;
|
|
21284
|
+
work = removeNestedTables(work);
|
|
21197
21285
|
}
|
|
21198
|
-
|
|
21199
|
-
|
|
21200
|
-
|
|
21201
|
-
paraPr(0, { lineSpacing: ls, keepWord: true }),
|
|
21202
|
-
paraPr(1, { align: titleAlign, spaceBefore: 400, spaceAfter: 400, lineSpacing: ls, keepWord: true }),
|
|
21203
|
-
paraPr(2, { align: "LEFT", spaceBefore: 600, spaceAfter: 150, lineSpacing: ls, keepWord: true }),
|
|
21204
|
-
paraPr(3, { align: "LEFT", spaceBefore: 400, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21205
|
-
paraPr(4, { align: "LEFT", spaceBefore: 300, spaceAfter: 100, lineSpacing: ls, keepWord: true }),
|
|
21206
|
-
paraPr(5, { align: "LEFT", lineSpacing: 130, indent: 400, keepWord: true }),
|
|
21207
|
-
paraPr(6, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true }),
|
|
21208
|
-
paraPr(7, { align: "LEFT", lineSpacing: ls, indent: 600, keepWord: true })
|
|
21209
|
-
];
|
|
21210
|
-
for (let d = 0; d < GONGMUN_LIST_LEVELS; d++) {
|
|
21211
|
-
const { left, indent } = levelIndent(d, gongmun.bodyHeight, gongmun.numbering);
|
|
21212
|
-
const sectionGap = gongmun.numbering === "report" && d === 0 ? Math.round(gongmun.bodyHeight * 0.5) : 0;
|
|
21213
|
-
base.push(paraPr(GONGMUN_LIST_BASE + d, { align: "JUSTIFY", lineSpacing: ls, left, indent, spaceBefore: sectionGap, keepWord: true }));
|
|
21286
|
+
if (/<img\s/i.test(work)) {
|
|
21287
|
+
hadNonText = true;
|
|
21288
|
+
work = work.replace(/<img\s(?:"[^"]*"|'[^']*'|[^>"'])*?>/gi, "");
|
|
21214
21289
|
}
|
|
21215
|
-
|
|
21216
|
-
return
|
|
21217
|
-
${base.join("\n")}
|
|
21218
|
-
</hh:paraProperties>`;
|
|
21290
|
+
const lines = work.split(/<br\s*\/?>/gi).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
21291
|
+
return { lines, hadNonText };
|
|
21219
21292
|
}
|
|
21220
|
-
function
|
|
21221
|
-
const
|
|
21222
|
-
|
|
21223
|
-
|
|
21224
|
-
|
|
21225
|
-
|
|
21226
|
-
|
|
21227
|
-
|
|
21228
|
-
|
|
21229
|
-
|
|
21230
|
-
|
|
21231
|
-
|
|
21232
|
-
|
|
21233
|
-
|
|
21234
|
-
|
|
21235
|
-
|
|
21236
|
-
|
|
21237
|
-
|
|
21238
|
-
|
|
21239
|
-
|
|
21240
|
-
<hh:fontface lang="LATIN" fontCnt="3">
|
|
21241
|
-
<hh:font id="0" face="Times New Roman" type="TTF" isEmbedded="0">
|
|
21242
|
-
<hh:typeInfo familyType="FCAT_OLDSTYLE" weight="5" proportion="4" contrast="2" strokeVariation="0" armStyle="0" letterform="0" midline="0" xHeight="4"/>
|
|
21243
|
-
</hh:font>
|
|
21244
|
-
<hh:font id="1" face="Consolas" type="TTF" isEmbedded="0">
|
|
21245
|
-
<hh:typeInfo familyType="FCAT_MODERN" weight="5" proportion="0" contrast="0" strokeVariation="0" armStyle="0" letterform="0" midline="0" xHeight="0"/>
|
|
21246
|
-
</hh:font>
|
|
21247
|
-
<hh:font id="2" face="Arial Black" type="TTF" isEmbedded="0">
|
|
21248
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="9" proportion="0" contrast="0" strokeVariation="0" armStyle="0" letterform="0" midline="0" xHeight="0"/>
|
|
21249
|
-
</hh:font>
|
|
21250
|
-
</hh:fontface>
|
|
21251
|
-
<hh:fontface lang="HANJA" fontCnt="1">
|
|
21252
|
-
<hh:font id="0" face="\uD568\uCD08\uB86C\uBC14\uD0D5" type="TTF" isEmbedded="0">
|
|
21253
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="4" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21254
|
-
</hh:font>
|
|
21255
|
-
</hh:fontface>
|
|
21256
|
-
<hh:fontface lang="JAPANESE" fontCnt="1">
|
|
21257
|
-
<hh:font id="0" face="\uAD74\uB9BC" type="TTF" isEmbedded="0">
|
|
21258
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21259
|
-
</hh:font>
|
|
21260
|
-
</hh:fontface>
|
|
21261
|
-
<hh:fontface lang="OTHER" fontCnt="1">
|
|
21262
|
-
<hh:font id="0" face="\uAD74\uB9BC" type="TTF" isEmbedded="0">
|
|
21263
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21264
|
-
</hh:font>
|
|
21265
|
-
</hh:fontface>
|
|
21266
|
-
<hh:fontface lang="SYMBOL" fontCnt="1">
|
|
21267
|
-
<hh:font id="0" face="Symbol" type="TTF" isEmbedded="0">
|
|
21268
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21269
|
-
</hh:font>
|
|
21270
|
-
</hh:fontface>
|
|
21271
|
-
<hh:fontface lang="USER" fontCnt="1">
|
|
21272
|
-
<hh:font id="0" face="\uAD74\uB9BC" type="TTF" isEmbedded="0">
|
|
21273
|
-
<hh:typeInfo familyType="FCAT_GOTHIC" weight="6" proportion="0" contrast="0" strokeVariation="1" armStyle="1" letterform="1" midline="1" xHeight="1"/>
|
|
21274
|
-
</hh:font>
|
|
21275
|
-
</hh:fontface>
|
|
21276
|
-
</hh:fontfaces>
|
|
21277
|
-
<hh:borderFills itemCnt="2">
|
|
21278
|
-
<hh:borderFill id="1" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
21279
|
-
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
21280
|
-
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
21281
|
-
<hh:leftBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
21282
|
-
<hh:rightBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
21283
|
-
<hh:topBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
21284
|
-
<hh:bottomBorder type="NONE" width="0.1 mm" color="#000000"/>
|
|
21285
|
-
</hh:borderFill>
|
|
21286
|
-
<hh:borderFill id="2" threeD="0" shadow="0" centerLine="NONE" breakCellSeparateLine="0">
|
|
21287
|
-
<hh:slash type="NONE" Crooked="0" isCounter="0"/>
|
|
21288
|
-
<hh:backSlash type="NONE" Crooked="0" isCounter="0"/>
|
|
21289
|
-
<hh:leftBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
21290
|
-
<hh:rightBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
21291
|
-
<hh:topBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
21292
|
-
<hh:bottomBorder type="SOLID" width="0.12 mm" color="#000000"/>
|
|
21293
|
-
</hh:borderFill>
|
|
21294
|
-
</hh:borderFills>
|
|
21295
|
-
${charPropsXml}
|
|
21296
|
-
<hh:tabProperties itemCnt="0"/>
|
|
21297
|
-
<hh:numberings itemCnt="0"/>
|
|
21298
|
-
<hh:bullets itemCnt="0"/>
|
|
21299
|
-
${paraPropsXml}
|
|
21300
|
-
<hh:styles itemCnt="1">
|
|
21301
|
-
<hh:style id="0" type="PARA" name="\uBC14\uD0D5\uAE00" engName="Normal" paraPrIDRef="0" charPrIDRef="0" nextStyleIDRef="0" langIDRef="1042" lockForm="0"/>
|
|
21302
|
-
</hh:styles>
|
|
21303
|
-
</hh:refList>
|
|
21304
|
-
<hh:compatibleDocument targetProgram="HWP2018"><hh:layoutCompatibility/></hh:compatibleDocument>
|
|
21305
|
-
</hh:head>`;
|
|
21293
|
+
function extractTopLevelTables(html) {
|
|
21294
|
+
const result = [];
|
|
21295
|
+
let depth = 0;
|
|
21296
|
+
let start = -1;
|
|
21297
|
+
const re = /<(\/?)table(?:[\s>]|>)/gi;
|
|
21298
|
+
let m;
|
|
21299
|
+
while ((m = re.exec(html)) !== null) {
|
|
21300
|
+
if (m[1] !== "/") {
|
|
21301
|
+
if (depth === 0) start = m.index;
|
|
21302
|
+
depth++;
|
|
21303
|
+
} else {
|
|
21304
|
+
depth--;
|
|
21305
|
+
if (depth === 0 && start >= 0) {
|
|
21306
|
+
result.push(html.slice(start, m.index + m[0].length));
|
|
21307
|
+
start = -1;
|
|
21308
|
+
}
|
|
21309
|
+
if (depth < 0) depth = 0;
|
|
21310
|
+
}
|
|
21311
|
+
}
|
|
21312
|
+
return result;
|
|
21306
21313
|
}
|
|
21307
|
-
function
|
|
21308
|
-
|
|
21309
|
-
|
|
21310
|
-
|
|
21311
|
-
|
|
21312
|
-
|
|
21313
|
-
|
|
21314
|
-
|
|
21315
|
-
|
|
21316
|
-
|
|
21314
|
+
function removeNestedTables(html) {
|
|
21315
|
+
let result = "";
|
|
21316
|
+
let depth = 0;
|
|
21317
|
+
const re = /<(\/?)table(?:[\s>]|>)/gi;
|
|
21318
|
+
let last = 0;
|
|
21319
|
+
let m;
|
|
21320
|
+
while ((m = re.exec(html)) !== null) {
|
|
21321
|
+
if (m[1] !== "/") {
|
|
21322
|
+
if (depth === 0) result += html.slice(last, m.index);
|
|
21323
|
+
depth++;
|
|
21324
|
+
} else {
|
|
21325
|
+
depth--;
|
|
21326
|
+
if (depth === 0) last = m.index + m[0].length;
|
|
21327
|
+
if (depth < 0) depth = 0;
|
|
21328
|
+
}
|
|
21329
|
+
}
|
|
21330
|
+
if (depth === 0) result += html.slice(last);
|
|
21331
|
+
return result;
|
|
21317
21332
|
}
|
|
21333
|
+
|
|
21334
|
+
// src/hwpx/gen-table.ts
|
|
21318
21335
|
var TABLE_ID_BASE = 1e3;
|
|
21319
21336
|
var tableIdCounter = TABLE_ID_BASE;
|
|
21320
21337
|
function nextTableId() {
|
|
@@ -21404,41 +21421,18 @@ function generateHtmlTableXml(rawHtml, theme, totalWidth = 44e3) {
|
|
|
21404
21421
|
}
|
|
21405
21422
|
return `<hp:tbl id="${tblId}" zOrder="0" numberingType="TABLE" pageBreak="CELL" repeatHeader="0" rowCnt="${rowCnt}" colCnt="${colCnt}" cellSpacing="0" borderFillIDRef="2" noShading="0"><hp:sz width="${tblW}" widthRelTo="ABSOLUTE" height="${cellH * rowCnt}" heightRelTo="ABSOLUTE" protect="0"/><hp:pos treatAsChar="1" affectLSpacing="0" flowWithText="0" allowOverlap="0" holdAnchorAndSO="0" vertRelTo="PARA" horzRelTo="PARA" vertAlign="TOP" horzAlign="LEFT" vertOffset="0" horzOffset="0"/><hp:outMargin left="0" right="0" top="0" bottom="0"/><hp:inMargin left="510" right="510" top="141" bottom="141"/>` + trXmls.join("") + `</hp:tbl>`;
|
|
21406
21423
|
}
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
|
|
21410
|
-
|
|
21411
|
-
|
|
21412
|
-
|
|
21413
|
-
|
|
21414
|
-
|
|
21415
|
-
|
|
21416
|
-
|
|
21417
|
-
|
|
21418
|
-
|
|
21419
|
-
run.push(i);
|
|
21420
|
-
i++;
|
|
21421
|
-
continue;
|
|
21422
|
-
}
|
|
21423
|
-
if (t === "table" || t === "html_table") {
|
|
21424
|
-
let j = i + 1;
|
|
21425
|
-
while (j < blocks.length && (blocks[j].type === "table" || blocks[j].type === "html_table")) j++;
|
|
21426
|
-
if (j < blocks.length && blocks[j].type === "list_item") {
|
|
21427
|
-
i = j;
|
|
21428
|
-
continue;
|
|
21429
|
-
}
|
|
21430
|
-
}
|
|
21431
|
-
break;
|
|
21432
|
-
}
|
|
21433
|
-
const depths = run.map((bi) => Math.min(Math.max(blocks[bi].indent || 0, 0), GONGMUN_LIST_LEVELS - 1));
|
|
21434
|
-
const suppress = gongmun.numbering === "standard" ? computeSuppression(depths) : depths.map(() => false);
|
|
21435
|
-
const numberer = new GongmunNumberer(gongmun.numbering);
|
|
21436
|
-
run.forEach((bi, k) => {
|
|
21437
|
-
const marker = numberer.next(depths[k], suppress[k]);
|
|
21438
|
-
result.set(bi, { marker, depth: depths[k] });
|
|
21439
|
-
});
|
|
21440
|
-
}
|
|
21441
|
-
return result;
|
|
21424
|
+
|
|
21425
|
+
// src/hwpx/gen-section.ts
|
|
21426
|
+
function generateSecPr(gongmun) {
|
|
21427
|
+
const m = gongmun ? {
|
|
21428
|
+
top: mmToHwpunit(gongmun.margins.top),
|
|
21429
|
+
bottom: mmToHwpunit(gongmun.margins.bottom),
|
|
21430
|
+
left: mmToHwpunit(gongmun.margins.left),
|
|
21431
|
+
right: mmToHwpunit(gongmun.margins.right),
|
|
21432
|
+
header: 0,
|
|
21433
|
+
footer: 0
|
|
21434
|
+
} : { top: 8504, bottom: 4252, left: 5670, right: 4252, header: 2835, footer: 2835 };
|
|
21435
|
+
return `<hp:secPr 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:pagePr landscape="WIDELY" width="59528" height="84188" gutterType="LEFT_ONLY"><hp:margin header="${m.header}" footer="${m.footer}" gutter="0" left="${m.left}" right="${m.right}" top="${m.top}" bottom="${m.bottom}"/></hp:pagePr><hp:footNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="-1" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="283" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="EACH_COLUMN" beneathText="0"/></hp:footNotePr><hp:endNotePr><hp:autoNumFormat type="DIGIT" userChar="" prefixChar="" suffixChar=")" supscript="0"/><hp:noteLine length="14692344" type="SOLID" width="0.12 mm" color="#000000"/><hp:noteSpacing betweenNotes="0" belowLine="567" aboveLine="850"/><hp:numbering type="CONTINUOUS" newNum="1"/><hp:placement place="END_OF_DOCUMENT" beneathText="0"/></hp:endNotePr></hp:secPr>`;
|
|
21442
21436
|
}
|
|
21443
21437
|
function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null, fit = null) {
|
|
21444
21438
|
const paraXmls = [];
|
|
@@ -21561,6 +21555,24 @@ function blocksToSectionXml(blocks, theme, gongmun, gongmunList = gongmun ? prec
|
|
|
21561
21555
|
</hs:sec>`;
|
|
21562
21556
|
}
|
|
21563
21557
|
|
|
21558
|
+
// src/hwpx/generator.ts
|
|
21559
|
+
async function markdownToHwpx(markdown, options) {
|
|
21560
|
+
const theme = resolveTheme(options?.theme);
|
|
21561
|
+
const gongmun = options?.gongmun ? resolveGongmun(options.gongmun) : null;
|
|
21562
|
+
const blocks = parseMarkdownToBlocks(markdown);
|
|
21563
|
+
const gongmunList = gongmun ? precomputeGongmunList(blocks, gongmun) : null;
|
|
21564
|
+
const fit = gongmun && gongmunList ? computeGongmunFitPlan(blocks, gongmun, gongmunList) : null;
|
|
21565
|
+
const sectionXml = blocksToSectionXml(blocks, theme, gongmun, gongmunList, fit);
|
|
21566
|
+
const zip = new JSZip6();
|
|
21567
|
+
zip.file("mimetype", "application/hwp+zip", { compression: "STORE" });
|
|
21568
|
+
zip.file("META-INF/container.xml", generateContainerXml());
|
|
21569
|
+
zip.file("Contents/content.hpf", generateManifest());
|
|
21570
|
+
zip.file("Contents/header.xml", generateHeaderXml(theme, gongmun, fit?.variants ?? []));
|
|
21571
|
+
zip.file("Contents/section0.xml", sectionXml);
|
|
21572
|
+
zip.file("Preview/PrvText.txt", buildPrvText(blocks));
|
|
21573
|
+
return await zip.generateAsync({ type: "arraybuffer" });
|
|
21574
|
+
}
|
|
21575
|
+
|
|
21564
21576
|
// src/diff/compare.ts
|
|
21565
21577
|
var SIMILARITY_THRESHOLD = 0.4;
|
|
21566
21578
|
async function compare(bufferA, bufferB, options) {
|
|
@@ -24285,7 +24297,7 @@ async function parseHwp(buffer, options) {
|
|
|
24285
24297
|
async function parsePdf(buffer, options) {
|
|
24286
24298
|
let parsePdfDocument;
|
|
24287
24299
|
try {
|
|
24288
|
-
const mod = await import("./parser-
|
|
24300
|
+
const mod = await import("./parser-KNQDRLZQ.js");
|
|
24289
24301
|
parsePdfDocument = mod.parsePdfDocument;
|
|
24290
24302
|
} catch {
|
|
24291
24303
|
return {
|
|
@@ -24420,4 +24432,4 @@ export {
|
|
|
24420
24432
|
parseHwpml,
|
|
24421
24433
|
fillForm
|
|
24422
24434
|
};
|
|
24423
|
-
//# sourceMappingURL=chunk-
|
|
24435
|
+
//# sourceMappingURL=chunk-DP37KF2X.js.map
|