@makhmudov.kay/az-editor 0.1.0-beta.2 → 0.1.0-beta.3
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 +70 -70
- package/dist/az-editor.js +283 -208
- package/dist/library/hujjat/table-grid.d.ts +8 -0
- package/docs/integration.ru.md +896 -875
- package/package.json +1 -1
package/dist/az-editor.js
CHANGED
|
@@ -443,22 +443,22 @@ function ie(e, t, n) {
|
|
|
443
443
|
}
|
|
444
444
|
//#endregion
|
|
445
445
|
//#region src/library/hujjat/xml.ts
|
|
446
|
-
var
|
|
446
|
+
var P = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", F = (e) => e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"), I = (e, t) => Array.from(e?.children ?? []).filter((e) => e.namespaceURI === "http://schemas.openxmlformats.org/wordprocessingml/2006/main" && (!t || e.localName === t)), L = (e, t) => I(e, t)[0] ?? null, R = (e, t = "val") => e?.getAttributeNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", t) ?? "", z = (e, t) => R(L(e, t)), B = (e) => e !== null && ![
|
|
447
447
|
"0",
|
|
448
448
|
"false",
|
|
449
449
|
"off",
|
|
450
450
|
"none"
|
|
451
|
-
].includes(
|
|
452
|
-
function
|
|
451
|
+
].includes(R(e)), V = (e) => `${Number(e) / 20}pt`, H = (e) => Object.keys(e).length ? ` style="${F(Object.entries(e).map(([e, t]) => `${e}:${t}`).join(";"))}"` : "";
|
|
452
|
+
function ae(e) {
|
|
453
453
|
if (/<!DOCTYPE|<!ENTITY/i.test(e)) throw new C("XML с DTD/ENTITY не поддерживается.");
|
|
454
454
|
let t = new DOMParser().parseFromString(e, "application/xml");
|
|
455
455
|
if (t.querySelector("parsererror")) throw new C("Повреждённый XML в DOCX.");
|
|
456
456
|
if (t.getElementsByTagName("*").length > 5e4) throw new C("Слишком сложный XML в DOCX.");
|
|
457
457
|
return t;
|
|
458
458
|
}
|
|
459
|
-
async function
|
|
459
|
+
async function U(e, t) {
|
|
460
460
|
let n = e.file(t);
|
|
461
|
-
return n ?
|
|
461
|
+
return n ? ae(await new Promise((e, t) => {
|
|
462
462
|
let r = n.internalStream("uint8array"), i = 0, a = [];
|
|
463
463
|
r.on("data", (e) => {
|
|
464
464
|
i += e.length, i > 8388608 ? (r.pause(), t(new C("XML-часть DOCX превышает 8 МиБ."))) : a.push(e);
|
|
@@ -469,11 +469,11 @@ async function H(e, t) {
|
|
|
469
469
|
}), r.resume();
|
|
470
470
|
})) : null;
|
|
471
471
|
}
|
|
472
|
-
function
|
|
472
|
+
function W(e) {
|
|
473
473
|
let t = {};
|
|
474
|
-
|
|
475
|
-
let n =
|
|
476
|
-
r && (t["font-family"] = r),
|
|
474
|
+
L(e, "vanish") && (t["--az-hidden"] = B(L(e, "vanish")) ? "1" : "0");
|
|
475
|
+
let n = L(e, "rFonts"), r = R(n, "ascii") || R(n, "hAnsi") || R(n, "cs");
|
|
476
|
+
r && (t["font-family"] = r), z(e, "sz") && (t["font-size"] = `${Number(z(e, "sz")) / 2}pt`);
|
|
477
477
|
for (let [n, r, i, a] of [[
|
|
478
478
|
"b",
|
|
479
479
|
"font-weight",
|
|
@@ -484,46 +484,46 @@ function U(e) {
|
|
|
484
484
|
"font-style",
|
|
485
485
|
"italic",
|
|
486
486
|
"normal"
|
|
487
|
-
]])
|
|
487
|
+
]]) L(e, n) && (t[r] = B(L(e, n)) ? i : a);
|
|
488
488
|
let i = [];
|
|
489
|
-
|
|
490
|
-
let a =
|
|
489
|
+
L(e, "u") && (B(L(e, "u")) ? i.push("underline") : t["text-decoration"] = "none"), (B(L(e, "strike")) || B(L(e, "dstrike"))) && i.push("line-through"), i.length && (t["text-decoration"] = i.join(" "));
|
|
490
|
+
let a = z(e, "color");
|
|
491
491
|
/^[\da-f]{6}$/i.test(a) && (t.color = `#${a}`);
|
|
492
|
-
let o = L(
|
|
493
|
-
return /^[\da-f]{6}$/i.test(o) ? t["background-color"] = `#${o}` :
|
|
492
|
+
let o = R(L(e, "shd"), "fill");
|
|
493
|
+
return /^[\da-f]{6}$/i.test(o) ? t["background-color"] = `#${o}` : z(e, "highlight") && z(e, "highlight") !== "none" && (t["background-color"] = z(e, "highlight")), ["superscript", "subscript"].includes(z(e, "vertAlign")) && (t["vertical-align"] = z(e, "vertAlign") === "superscript" ? "super" : "sub"), B(L(e, "caps")) && (t["text-transform"] = "uppercase"), z(e, "spacing") && (t["letter-spacing"] = V(z(e, "spacing"))), t;
|
|
494
494
|
}
|
|
495
|
-
function
|
|
496
|
-
let t = {}, n =
|
|
495
|
+
function oe(e) {
|
|
496
|
+
let t = {}, n = z(e, "jc");
|
|
497
497
|
n && (t["text-align"] = {
|
|
498
498
|
both: "justify",
|
|
499
499
|
distribute: "justify",
|
|
500
500
|
start: "left",
|
|
501
501
|
end: "right"
|
|
502
502
|
}[n] ?? n);
|
|
503
|
-
let r =
|
|
504
|
-
for (let [e, n] of [["before", "margin-top"], ["after", "margin-bottom"]])
|
|
505
|
-
|
|
506
|
-
let i =
|
|
503
|
+
let r = L(e, "spacing");
|
|
504
|
+
for (let [e, n] of [["before", "margin-top"], ["after", "margin-bottom"]]) R(r, e) && (t[n] = V(R(r, e)));
|
|
505
|
+
R(r, "line") && (t["line-height"] = R(r, "lineRule") === "auto" || !R(r, "lineRule") ? String(Number(R(r, "line")) / 240) : V(R(r, "line")));
|
|
506
|
+
let i = L(e, "ind");
|
|
507
507
|
for (let [e, n] of [
|
|
508
508
|
["left", "margin-left"],
|
|
509
509
|
["right", "margin-right"],
|
|
510
510
|
["firstLine", "text-indent"]
|
|
511
|
-
])
|
|
512
|
-
return
|
|
511
|
+
]) R(i, e) && (t[n] = V(R(i, e)));
|
|
512
|
+
return R(i, "hanging") && (t["text-indent"] = V(-Number(R(i, "hanging")))), B(L(e, "pageBreakBefore")) && (t["page-break-before"] = "always"), B(L(e, "keepNext")) && (t["page-break-after"] = "avoid"), B(L(e, "keepLines")) && (t["page-break-inside"] = "avoid"), t;
|
|
513
513
|
}
|
|
514
|
-
function
|
|
514
|
+
function se(e) {
|
|
515
515
|
if (!e) return;
|
|
516
|
-
if (["nil", "none"].includes(
|
|
516
|
+
if (["nil", "none"].includes(R(e))) return "none";
|
|
517
517
|
let t = {
|
|
518
518
|
double: "double",
|
|
519
519
|
dotted: "dotted",
|
|
520
520
|
dashed: "dashed"
|
|
521
|
-
}[
|
|
522
|
-
return `${Number(
|
|
521
|
+
}[R(e)] ?? "solid", n = R(e, "color");
|
|
522
|
+
return `${Number(R(e, "sz") || 4) / 8}pt ${t} ${/^[\da-f]{6}$/i.test(n) ? "#" + n : "#000000"}`;
|
|
523
523
|
}
|
|
524
524
|
//#endregion
|
|
525
525
|
//#region src/library/hujjat/docx-to-html.ts
|
|
526
|
-
async function
|
|
526
|
+
async function ce(e) {
|
|
527
527
|
if (e.byteLength > 31457280) throw new C("DOCX превышает 30 МиБ.");
|
|
528
528
|
let t;
|
|
529
529
|
try {
|
|
@@ -534,48 +534,48 @@ async function le(e) {
|
|
|
534
534
|
let n = Object.keys(t.files);
|
|
535
535
|
if (n.length > 2e3) throw new C("В DOCX более 2000 частей.");
|
|
536
536
|
if (n.some((e) => /vbaProject\.bin$/i.test(e))) throw new C("DOCX с макросами не поддерживается.");
|
|
537
|
-
let r = await
|
|
537
|
+
let r = await U(t, "[Content_Types].xml");
|
|
538
538
|
if (!Array.from(r?.getElementsByTagNameNS("*", "Override") ?? []).some((e) => e.getAttribute("PartName") === "/word/document.xml" && e.getAttribute("ContentType") === "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")) throw new C("Файл не является обычным DOCX.");
|
|
539
|
-
let i = await
|
|
539
|
+
let i = await U(t, "word/document.xml"), a = await U(t, "word/styles.xml"), o = await U(t, "word/numbering.xml"), s = L(i?.documentElement, "body");
|
|
540
540
|
if (!s) throw new C("В DOCX нет поддерживаемой структуры документа.");
|
|
541
541
|
let c = [], l = (e, t) => w(c, e, t, "loss");
|
|
542
542
|
n.some((e) => /^word\/(header|footer)[^/]*\.xml$/.test(e)) && l("header-footer-removed", "Колонтитулы Word не входят в HTML-блок; футер формирует Hujjat."), n.some((e) => /^word\/comments/.test(e)) && l("review-removed", "Комментарии Word не сохраняются в HTML.");
|
|
543
|
-
let u =
|
|
543
|
+
let u = L(a?.documentElement, "docDefaults"), f = {
|
|
544
544
|
"margin-top": "0pt",
|
|
545
545
|
"margin-bottom": "8px",
|
|
546
|
-
...
|
|
546
|
+
...oe(L(L(u, "pPrDefault"), "pPr"))
|
|
547
547
|
}, p = {
|
|
548
548
|
"font-family": "freeserif",
|
|
549
549
|
"font-size": "12pt",
|
|
550
550
|
color: "#111111",
|
|
551
|
-
...
|
|
552
|
-
}, m = new Map(
|
|
551
|
+
...W(L(L(u, "rPrDefault"), "rPr"))
|
|
552
|
+
}, m = new Map(I(a?.documentElement, "style").map((e) => [R(e, "styleId"), e]));
|
|
553
553
|
function h(e, t = /* @__PURE__ */ new Set()) {
|
|
554
554
|
if (!e || t.has(e) || t.size > 30) return [];
|
|
555
555
|
t.add(e);
|
|
556
556
|
let n = m.get(e);
|
|
557
|
-
return n ? [...h(
|
|
557
|
+
return n ? [...h(z(n, "basedOn"), t), n] : [];
|
|
558
558
|
}
|
|
559
|
-
let g =
|
|
559
|
+
let g = I(a?.documentElement, "style").find((e) => R(e, "type") === "paragraph" && R(e, "default") === "1"), _ = new Map(I(o?.documentElement, "num").map((e) => [R(e, "numId"), e])), v = new Map(I(o?.documentElement, "abstractNum").map((e) => [R(e, "abstractNumId"), e])), y = /* @__PURE__ */ new Set(), b = !1, x = 0, S = (e) => {
|
|
560
560
|
if (++x > 5e4 || e > 80) throw new C("DOCX слишком сложный для HTML-адаптера.");
|
|
561
561
|
};
|
|
562
562
|
function T(e, t, n) {
|
|
563
563
|
if (S(n), e.namespaceURI !== "http://schemas.openxmlformats.org/wordprocessingml/2006/main") return l("unsupported-content", "Нестандартный объект Word не сохраняется в HTML."), "";
|
|
564
564
|
switch (e.localName) {
|
|
565
|
-
case "t": return
|
|
565
|
+
case "t": return F(Array.from(e.textContent ?? "").map((e) => {
|
|
566
566
|
let t = e === " " && b ? "\xA0" : e;
|
|
567
567
|
return b = e === " ", t;
|
|
568
568
|
}).join(""));
|
|
569
569
|
case "tab": return w(c, "tab-normalized", "Табуляция заменена пробелом; для выравнивания используйте таблицу."), " ";
|
|
570
|
-
case "br": return
|
|
570
|
+
case "br": return R(e, "type") === "page" ? "<div style=\"page-break-before:always\"></div>" : "<br>";
|
|
571
571
|
case "cr": return "<br>";
|
|
572
572
|
case "noBreakHyphen": return "‑";
|
|
573
573
|
case "softHyphen": return "";
|
|
574
574
|
case "r": {
|
|
575
|
-
let r =
|
|
575
|
+
let r = L(e, "rPr"), i = Object.assign({}, t, ...h(z(r, "rStyle")).map((e) => W(L(e, "rPr"))), W(r));
|
|
576
576
|
if (i["--az-hidden"] === "1") return l("hidden-text-removed", "Скрытый текст Word исключён из HTML."), "";
|
|
577
577
|
let a = Object.fromEntries(Object.entries(i).filter(([e]) => e !== "--az-hidden"));
|
|
578
|
-
return
|
|
578
|
+
return I(e).filter((e) => e.localName !== "rPr").map((e) => T(e, i, n + 1)).join("").split(/(<div style="page-break-before:always"><\/div>)/).map((e) => e.startsWith("<div ") ? e : e ? `<span${H(a)}>${e}</span>` : "").join("");
|
|
579
579
|
}
|
|
580
580
|
case "hyperlink":
|
|
581
581
|
w(c, "hyperlink-removed", "Ссылки сохраняются как текст без перехода.");
|
|
@@ -596,7 +596,7 @@ async function le(e) {
|
|
|
596
596
|
case "fldSimple":
|
|
597
597
|
l("field-flattened", "Поля Word сохраняют только имеющийся текстовый результат.");
|
|
598
598
|
break;
|
|
599
|
-
case "sdt": return l("content-control-flattened", "Элементы управления Word преобразуются в обычный текст."),
|
|
599
|
+
case "sdt": return l("content-control-flattened", "Элементы управления Word преобразуются в обычный текст."), L(e, "sdtContent") ? T(L(e, "sdtContent"), t, n + 1) : "";
|
|
600
600
|
case "sdtContent":
|
|
601
601
|
case "smartTag":
|
|
602
602
|
case "customXml": break;
|
|
@@ -612,77 +612,82 @@ async function le(e) {
|
|
|
612
612
|
return Array.from(e.children).map((e) => T(e, t, n + 1)).join("");
|
|
613
613
|
}
|
|
614
614
|
function E(e, t) {
|
|
615
|
-
let n =
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
615
|
+
let n = L(e, "pPr"), r = h(z(n, "pStyle") || R(g, "styleId")), i = [...r.map((e) => L(e, "pPr")), n], a = Object.assign({}, f, ...i.map(oe)), o = Object.assign({}, p, ...r.map((e) => W(L(e, "rPr")))), s = Array.from(e.getElementsByTagNameNS(P, "r")).map((e) => {
|
|
616
|
+
let t = L(e, "rPr"), n = Object.assign({}, o, ...h(z(t, "rStyle")).map((e) => W(L(e, "rPr"))), W(t));
|
|
617
|
+
return parseFloat(n["font-size"]) || 12;
|
|
618
|
+
}), l = a["line-height"];
|
|
619
|
+
l && (/^\d*\.?\d+$/.test(l) ? Number(l) < 1 : l.endsWith("pt") && parseFloat(l) < Math.max(parseFloat(o["font-size"]) || 12, ...s)) && (a["line-height"] = /^\d*\.?\d+$/.test(l) ? "1" : "normal", w(c, "line-height-normalized", "Слишком маленький межстрочный интервал заменён безопасным, чтобы строки не перекрывались.")), L(n, "tabs") && w(c, "tab-stops-removed", "Позиции табуляции не поддерживаются HTML-блоком."), L(n, "sectPr") && w(c, "section-normalized", "Разделы Word приводятся к странице A4 Hujjat."), b = !0;
|
|
620
|
+
let u = Array.from(e.children).filter((e) => e !== n).map((e) => T(e, o, t + 1)).join("").split("<div style=\"page-break-before:always\"></div>").map((e, t) => `${t ? "<div style=\"page-break-before:always\"></div>" : ""}<p${H(a)}>${e || "<br>"}</p>`).join(""), d = i.map((e) => L(e, "numPr")).filter(Boolean).at(-1), m = z(d, "numId"), y = Number(z(d, "ilvl") || 0);
|
|
621
|
+
if (m && m !== "0") {
|
|
622
|
+
let e = _.get(m), t = I(v.get(z(e, "abstractNumId")), "lvl").find((e) => R(e, "ilvl") === String(y));
|
|
623
|
+
if (!t) return w(c, "numbering-unsupported", "Не найдена нумерация списка.", "loss"), { html: u };
|
|
624
|
+
let n = z(t, "numFmt");
|
|
625
|
+
return (!["decimal", "bullet"].includes(n) || y || z(t, "start") && z(t, "start") !== "1" || L(e, "lvlOverride")) && w(c, "numbering-normalized", "Сложная нумерация/начальное число списка заменены обычным HTML-списком.", "loss"), {
|
|
626
|
+
html: u,
|
|
624
627
|
list: {
|
|
625
|
-
id:
|
|
626
|
-
level: Math.min(
|
|
628
|
+
id: m,
|
|
629
|
+
level: Math.min(y, 8),
|
|
627
630
|
tag: n === "bullet" ? "ul" : "ol"
|
|
628
631
|
}
|
|
629
632
|
};
|
|
630
633
|
}
|
|
631
634
|
return {
|
|
632
|
-
html:
|
|
633
|
-
continuation:
|
|
635
|
+
html: u,
|
|
636
|
+
continuation: z(n, "pStyle") === "AzHujjatListContinuation"
|
|
634
637
|
};
|
|
635
638
|
}
|
|
636
639
|
function D(e, t) {
|
|
637
640
|
S(t);
|
|
638
|
-
let n =
|
|
639
|
-
|
|
640
|
-
let r =
|
|
641
|
-
|
|
642
|
-
let
|
|
643
|
-
Number(
|
|
644
|
-
for (let
|
|
645
|
-
let e =
|
|
646
|
-
if (
|
|
647
|
-
if (
|
|
648
|
-
let e =
|
|
641
|
+
let n = L(e, "tblPr");
|
|
642
|
+
z(n, "tblStyle") && w(c, "table-style-normalized", "Условные стили таблиц Word могут отличаться; проверьте границы и заливку.");
|
|
643
|
+
let r = L(n, "tblBorders"), i = I(L(e, "tblGrid"), "gridCol").map((e) => Number(R(e, "w"))), a = R(L(n, "tblLayout"), "type") === "fixed", o = I(e, "tr"), s = /* @__PURE__ */ new Map(), u = Math.max(1, ...o.map((e) => I(e, "tc").reduce((e, t) => e + Number(z(L(t, "tcPr"), "gridSpan") || 1), 0))), d = [];
|
|
644
|
+
o.forEach((e, c) => {
|
|
645
|
+
let f = 0, p = [];
|
|
646
|
+
Number(z(L(e, "trPr"), "gridBefore") || 0) && l("table-grid-unsupported", "Таблица с пропущенными начальными ячейками требует проверки.");
|
|
647
|
+
for (let d of I(e, "tc")) {
|
|
648
|
+
let e = L(d, "tcPr"), m = Number(z(e, "gridSpan") || 1), h = L(e, "vMerge");
|
|
649
|
+
if (L(e, "hMerge") && l("legacy-table-merge", "Старый формат горизонтального объединения hMerge требует преобразования в gridSpan."), !Number.isInteger(m) || m < 1 || m > 100) throw new C("Объединение таблицы превышает предел 100 ячеек.");
|
|
650
|
+
if (h && R(h) !== "restart" && s.has(f) && s.get(f).span === m) {
|
|
651
|
+
let e = s.get(f);
|
|
649
652
|
if (e.rowSpan++, e.rowSpan > 100) throw new C("Объединение таблицы превышает 100 строк.");
|
|
650
|
-
|
|
653
|
+
d.getElementsByTagNameNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "t").length && d.textContent?.trim() && l("table-merge-content", "Текст в продолжении объединённой ячейки требует ручной проверки."), f += m;
|
|
651
654
|
continue;
|
|
652
655
|
}
|
|
653
|
-
let
|
|
654
|
-
|
|
655
|
-
let
|
|
656
|
-
|
|
656
|
+
let g = {}, _ = L(e, "tcW");
|
|
657
|
+
R(_, "type") === "dxa" ? g.width = V(R(_, "w")) : R(_, "type") === "pct" && (g.width = `${Number(R(_, "w")) / 50}%`);
|
|
658
|
+
let v = i.slice(f, f + m);
|
|
659
|
+
(a || !g.width) && v.length === m && v.every((e) => Number.isFinite(e) && e > 0) && (g.width = V(v.reduce((e, t) => e + t, 0)));
|
|
660
|
+
let y = R(L(e, "shd"), "fill");
|
|
661
|
+
/^[\da-f]{6}$/i.test(y) && (g["background-color"] = "#" + y), z(e, "vAlign") && (g["vertical-align"] = z(e, "vAlign") === "center" ? "middle" : z(e, "vAlign"));
|
|
657
662
|
for (let t of [
|
|
658
663
|
"top",
|
|
659
664
|
"right",
|
|
660
665
|
"bottom",
|
|
661
666
|
"left"
|
|
662
667
|
]) {
|
|
663
|
-
let
|
|
664
|
-
|
|
665
|
-
let
|
|
666
|
-
|
|
668
|
+
let i = L(L(e, "tcBorders"), t), a = t === "top" && c > 0 || t === "bottom" && c < o.length - 1 ? "insideH" : t === "left" && f > 0 || t === "right" && f + m < u ? "insideV" : t, s = L(r, a), l = se(i ?? s);
|
|
669
|
+
l && (g[`border-${t}`] = l);
|
|
670
|
+
let d = L(L(e, "tcMar"), t) ?? L(L(n, "tblCellMar"), t);
|
|
671
|
+
d && R(d, "w") && (g[`padding-${t}`] = V(R(d, "w")));
|
|
667
672
|
}
|
|
668
|
-
let
|
|
669
|
-
element:
|
|
673
|
+
let b = {
|
|
674
|
+
element: d,
|
|
670
675
|
rowSpan: 1,
|
|
671
|
-
span:
|
|
672
|
-
html: O(
|
|
673
|
-
css:
|
|
676
|
+
span: m,
|
|
677
|
+
html: O(d, t + 1),
|
|
678
|
+
css: g
|
|
674
679
|
};
|
|
675
|
-
for (let e =
|
|
676
|
-
|
|
680
|
+
for (let e = f; e < f + m; e++) s.delete(e);
|
|
681
|
+
h && R(h) === "restart" && s.set(f, b), p.push(b), f += m;
|
|
677
682
|
}
|
|
678
|
-
for (let e of
|
|
679
|
-
|
|
683
|
+
for (let e of s.keys()) e >= f && s.delete(e);
|
|
684
|
+
d.push(p);
|
|
680
685
|
});
|
|
681
|
-
let
|
|
682
|
-
|
|
683
|
-
width: L(u, "type") === "dxa" ? B(L(u, "w")) : L(u, "type") === "pct" ? `${Number(L(u, "w")) / 50}%` : "100%",
|
|
686
|
+
let f = L(n, "tblW"), p = {
|
|
687
|
+
width: R(f, "type") === "dxa" ? V(R(f, "w")) : R(f, "type") === "pct" ? `${Number(R(f, "w")) / 50}%` : "100%",
|
|
684
688
|
"border-collapse": "collapse"
|
|
685
|
-
}
|
|
689
|
+
};
|
|
690
|
+
return a && (p["table-layout"] = "fixed"), `<table${H(p)}>${d.map((e) => `<tr>${e.map((e) => `<td${e.span > 1 ? ` colspan="${e.span}"` : ""}${e.rowSpan > 1 ? ` rowspan="${e.rowSpan}"` : ""}${H(e.css)}>${e.html || "<p><br></p>"}</td>`).join("")}</tr>`).join("")}</table>`;
|
|
686
691
|
}
|
|
687
692
|
function O(e, t) {
|
|
688
693
|
S(t);
|
|
@@ -695,8 +700,8 @@ async function le(e) {
|
|
|
695
700
|
e.list ? ((r?.id !== e.list.id || r.tag !== e.list.tag) && (i(), r = e.list, r.tag === "ol" && y.has(r.id) && l("numbering-restart", "Продолжение нумерованного списка после другого блока начнётся с 1: Hujjat удаляет атрибут start."), y.add(r.id), n += `<${r.tag}>`), n += `<li>${e.html}</li>`) : e.continuation && r && n.endsWith("</li>") ? n = n.slice(0, -5) + e.html + "</li>" : (i(), n += e.html);
|
|
696
701
|
} else if (a.localName === "tbl") i(), n += D(a, t + 1);
|
|
697
702
|
else if (a.localName === "sectPr") {
|
|
698
|
-
let e =
|
|
699
|
-
(
|
|
703
|
+
let e = L(a, "pgSz"), t = L(a, "pgMar");
|
|
704
|
+
(R(e, "orient") === "landscape" || R(e, "w") && Math.abs(Number(R(e, "w")) - 11906) > 2 || R(t, "bottom") && Math.abs(Number(R(t, "bottom")) - 1984) > 2) && w(c, "page-normalized", "Размеры и поля Word заменяются настройками Hujjat: A4, 15/20/35/20 мм.");
|
|
700
705
|
} else [
|
|
701
706
|
"sdt",
|
|
702
707
|
"customXml",
|
|
@@ -704,7 +709,7 @@ async function le(e) {
|
|
|
704
709
|
"del",
|
|
705
710
|
"moveFrom",
|
|
706
711
|
"moveTo"
|
|
707
|
-
].includes(a.localName) ? (i(), l("block-flattened", `Блок Word ${a.localName} преобразован без интерактивности/истории.`), ["del", "moveFrom"].includes(a.localName) || (n += O(
|
|
712
|
+
].includes(a.localName) ? (i(), l("block-flattened", `Блок Word ${a.localName} преобразован без интерактивности/истории.`), ["del", "moveFrom"].includes(a.localName) || (n += O(L(a, "sdtContent") ?? a, t + 1))) : [
|
|
708
713
|
"tblPr",
|
|
709
714
|
"tblGrid",
|
|
710
715
|
"tcPr",
|
|
@@ -721,8 +726,44 @@ async function le(e) {
|
|
|
721
726
|
};
|
|
722
727
|
}
|
|
723
728
|
//#endregion
|
|
729
|
+
//#region src/library/hujjat/table-grid.ts
|
|
730
|
+
function le(e, t, n, r) {
|
|
731
|
+
let i = Array.from({ length: e }), a = () => w(r, "table-width-normalized", "Противоречивые ширины ячеек приведены к общей сетке таблицы.");
|
|
732
|
+
for (let e of [...n].sort((e, t) => e.span - t.span)) {
|
|
733
|
+
let t = Array.from({ length: e.span }, (t, n) => e.column + n), n = t.filter((e) => i[e] === void 0), r = t.reduce((e, t) => e + (i[t] ?? 0), 0);
|
|
734
|
+
if (!n.length) {
|
|
735
|
+
Math.abs(r - e.width) > 2 && a();
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
if (e.width <= r) {
|
|
739
|
+
a();
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
let o = (e.width - r) / n.length;
|
|
743
|
+
for (let e of n) i[e] = o;
|
|
744
|
+
}
|
|
745
|
+
let o = i.reduce((e, t) => e + (t ?? 0), 0), s = i.filter((e) => e === void 0).length, c = o < t ? (t - o) / Math.max(1, s) : t / e, l = i.map((e) => e ?? c), u = l.reduce((e, t) => e + t, 0);
|
|
746
|
+
o > t + 2 && a();
|
|
747
|
+
let d = Math.max(e, Math.round(t)), f = l.map((e) => e / u * d), p = f.map((e) => Math.max(1, Math.floor(e))), m = f.map((e, t) => ({
|
|
748
|
+
i: t,
|
|
749
|
+
fraction: e - p[t]
|
|
750
|
+
})).sort((e, t) => t.fraction - e.fraction), h = d - p.reduce((e, t) => e + t, 0);
|
|
751
|
+
for (let e = 0; e < h; e++) p[m[e].i]++;
|
|
752
|
+
if (h < 0) {
|
|
753
|
+
let e = -h;
|
|
754
|
+
for (let { i: t } of [...m].sort((e, t) => p[t.i] - p[e.i])) {
|
|
755
|
+
let n = Math.min(p[t] - 1, e);
|
|
756
|
+
if (p[t] -= n, e -= n, !e) break;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return p;
|
|
760
|
+
}
|
|
761
|
+
//#endregion
|
|
724
762
|
//#region src/library/hujjat/html-to-docx.ts
|
|
725
|
-
var ue =
|
|
763
|
+
var ue = {
|
|
764
|
+
width: 9638,
|
|
765
|
+
cell: !1
|
|
766
|
+
}, de = /^(font-|color$|text-align$|text-indent$|text-transform$|line-height$|letter-spacing$|white-space$|text-decoration$|vertical-align$)/, G = new Set("p div h1 h2 h3 h4 h5 h6 ul ol li table hr".split(" ")), fe = {
|
|
726
767
|
black: "000000",
|
|
727
768
|
white: "FFFFFF",
|
|
728
769
|
red: "FF0000",
|
|
@@ -741,14 +782,14 @@ var ue = /^(font-|color$|text-align$|text-indent$|text-transform$|line-height$|l
|
|
|
741
782
|
teal: "008080",
|
|
742
783
|
aqua: "00FFFF"
|
|
743
784
|
};
|
|
744
|
-
function
|
|
785
|
+
function K(e) {
|
|
745
786
|
if (!e) return;
|
|
746
787
|
if (/^#[\da-f]{6}$/i.test(e)) return e.slice(1);
|
|
747
788
|
if (/^#[\da-f]{3}$/i.test(e)) return e.slice(1).split("").map((e) => e + e).join("");
|
|
748
789
|
let t = e.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
|
|
749
|
-
return t ? t.slice(1).map((e) => Math.min(255, Number(e)).toString(16).padStart(2, "0")).join("") :
|
|
790
|
+
return t ? t.slice(1).map((e) => Math.min(255, Number(e)).toString(16).padStart(2, "0")).join("") : fe[e.toLowerCase()];
|
|
750
791
|
}
|
|
751
|
-
function
|
|
792
|
+
function q(e) {
|
|
752
793
|
if (e === "0") return 0;
|
|
753
794
|
let t = e?.match(/^(-?\d*\.?\d+)(pt|px|in|cm|mm|pc)$/i);
|
|
754
795
|
return t ? Number(t[1]) * {
|
|
@@ -760,11 +801,11 @@ function K(e) {
|
|
|
760
801
|
pc: 12
|
|
761
802
|
}[t[2].toLowerCase()] : void 0;
|
|
762
803
|
}
|
|
763
|
-
var
|
|
764
|
-
let t =
|
|
804
|
+
var J = (e) => {
|
|
805
|
+
let t = q(e);
|
|
765
806
|
return t === void 0 ? void 0 : Math.round(t * 20);
|
|
766
807
|
};
|
|
767
|
-
function
|
|
808
|
+
function Y(e, t) {
|
|
768
809
|
let n = { ...t }, r = e.style;
|
|
769
810
|
for (let e of Array.from(r)) n[e] = r.getPropertyValue(e).trim();
|
|
770
811
|
for (let e of ["margin", "padding"]) for (let t of [
|
|
@@ -783,8 +824,8 @@ function J(e, t) {
|
|
|
783
824
|
h3: "12pt"
|
|
784
825
|
}[i] ?? "12pt"), r.fontWeight || (n["font-weight"] = "bold")), n;
|
|
785
826
|
}
|
|
786
|
-
var
|
|
787
|
-
async function
|
|
827
|
+
var X = (e) => Object.fromEntries(Object.entries(e).filter(([e]) => de.test(e)));
|
|
828
|
+
async function pe(e, t) {
|
|
788
829
|
let n = j(e), r = 1, i = [], a = [];
|
|
789
830
|
function o() {
|
|
790
831
|
let e = !0;
|
|
@@ -806,7 +847,7 @@ async function fe(e, t) {
|
|
|
806
847
|
n || a.push(e);
|
|
807
848
|
return;
|
|
808
849
|
}
|
|
809
|
-
let r = e instanceof Element ? e : null, i = r && (
|
|
850
|
+
let r = e instanceof Element ? e : null, i = r && (G.has(r.localName) || [
|
|
810
851
|
"br",
|
|
811
852
|
"td",
|
|
812
853
|
"th",
|
|
@@ -823,34 +864,38 @@ async function fe(e, t) {
|
|
|
823
864
|
color: "#111111"
|
|
824
865
|
};
|
|
825
866
|
function l(e) {
|
|
826
|
-
let t = `<w:rFonts w:ascii="${
|
|
827
|
-
return n !== void 0 && (t += `<w:sz w:val="${Math.round(n * 2)}"/>`), e["font-weight"] && (t += `<w:b w:val="${e["font-weight"] === "bold" || Number(e["font-weight"]) >= 600 ? "1" : "0"}"/>`), e["font-style"] && (t += `<w:i w:val="${e["font-style"] === "italic" ? "1" : "0"}"/>`), e["text-decoration"] && (t += `<w:u w:val="${e["text-decoration"].includes("underline") ? "single" : "none"}"/><w:strike w:val="${e["text-decoration"].includes("line-through") ? "1" : "0"}"/>`),
|
|
867
|
+
let t = `<w:rFonts w:ascii="${F(e["font-family"] || "freeserif")}" w:hAnsi="${F(e["font-family"] || "freeserif")}"/>`, n = q(e["font-size"]);
|
|
868
|
+
return n !== void 0 && (t += `<w:sz w:val="${Math.round(n * 2)}"/>`), e["font-weight"] && (t += `<w:b w:val="${e["font-weight"] === "bold" || Number(e["font-weight"]) >= 600 ? "1" : "0"}"/>`), e["font-style"] && (t += `<w:i w:val="${e["font-style"] === "italic" ? "1" : "0"}"/>`), e["text-decoration"] && (t += `<w:u w:val="${e["text-decoration"].includes("underline") ? "single" : "none"}"/><w:strike w:val="${e["text-decoration"].includes("line-through") ? "1" : "0"}"/>`), K(e.color) && (t += `<w:color w:val="${K(e.color)}"/>`), K(e["background-color"]) && (t += `<w:shd w:fill="${K(e["background-color"])}"/>`), ["super", "sub"].includes(e["vertical-align"]) && (t += `<w:vertAlign w:val="${e["vertical-align"] === "super" ? "superscript" : "subscript"}"/>`), e["text-transform"] === "uppercase" && (t += "<w:caps/>"), J(e["letter-spacing"]) !== void 0 && (t += `<w:spacing w:val="${J(e["letter-spacing"])}"/>`), t;
|
|
828
869
|
}
|
|
829
870
|
function u(e, t) {
|
|
830
871
|
let n = "";
|
|
831
|
-
for (let r of e) r.nodeType === 3 ? r.textContent && (n += `<w:r><w:rPr>${l(t)}</w:rPr><w:t xml:space="preserve">${
|
|
872
|
+
for (let r of e) r.nodeType === 3 ? r.textContent && (n += `<w:r><w:rPr>${l(t)}</w:rPr><w:t xml:space="preserve">${F(r.textContent)}</w:t></w:r>`) : r instanceof Element && (r.localName === "br" ? n += "<w:r><w:br/></w:r>" : n += u(r.childNodes, Y(r, t)));
|
|
832
873
|
return n;
|
|
833
874
|
}
|
|
834
|
-
function f(e,
|
|
835
|
-
let
|
|
875
|
+
function f(e, n, r, i = ue) {
|
|
876
|
+
let a = "", o = n["text-align"];
|
|
836
877
|
[
|
|
837
878
|
"left",
|
|
838
879
|
"right",
|
|
839
880
|
"center",
|
|
840
881
|
"justify"
|
|
841
|
-
].includes(
|
|
842
|
-
let
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
882
|
+
].includes(o) && (a += `<w:jc w:val="${o === "justify" ? "both" : o}"/>`);
|
|
883
|
+
let s = J(n["margin-top"]) ?? 0, c = J(n["margin-bottom"]) ?? (i.cell ? 0 : 120), l = "", d = n["line-height"];
|
|
884
|
+
if (d && /^\d*\.?\d+%?$/.test(d)) {
|
|
885
|
+
let e = parseFloat(d) / (d.endsWith("%") ? 100 : 1);
|
|
886
|
+
e < 1 && w(t, "line-height-normalized", "Слишком маленький межстрочный интервал заменён безопасным, чтобы строки не перекрывались."), l = ` w:line="${Math.round(Math.max(1, e) * 240)}" w:lineRule="auto"`;
|
|
887
|
+
} else q(d) !== void 0 && (l = ` w:line="${Math.max(0, J(d))}" w:lineRule="atLeast"`);
|
|
888
|
+
a += `<w:spacing w:before="${Math.max(0, s)}" w:after="${Math.max(0, c)}"${l}/>`;
|
|
889
|
+
let f = "";
|
|
890
|
+
for (let [e, t] of [
|
|
846
891
|
["margin-left", "left"],
|
|
847
892
|
["margin-right", "right"],
|
|
848
893
|
["text-indent", "firstLine"]
|
|
849
894
|
]) {
|
|
850
|
-
let r =
|
|
851
|
-
r !== void 0 && (
|
|
895
|
+
let r = J(n[e]);
|
|
896
|
+
r !== void 0 && (f += t === "firstLine" && r < 0 ? ` w:hanging="${-r}"` : ` w:${t}="${r}"`);
|
|
852
897
|
}
|
|
853
|
-
return
|
|
898
|
+
return f && (a += `<w:ind${f}/>`), n["page-break-before"] === "always" && (a += "<w:pageBreakBefore/>"), n["page-break-inside"] === "avoid" && (a += "<w:keepLines/>"), n["page-break-after"] === "avoid" && (a += "<w:keepNext/>"), r && (r.pending ? a += `<w:numPr><w:ilvl w:val="0"/><w:numId w:val="${r.id}"/></w:numPr>` : a += "<w:pStyle w:val=\"AzHujjatListContinuation\"/>", r.pending = !1), `<w:p><w:pPr>${a}</w:pPr>${u(e, n)}</w:p>` + (n["page-break-after"] === "always" ? "<w:p><w:pPr><w:pageBreakBefore/></w:pPr></w:p>" : "");
|
|
854
899
|
}
|
|
855
900
|
function p(e, t) {
|
|
856
901
|
let n = e.style, r = n.getPropertyValue(`border-${t}-style`) || n.borderStyle, i = n.getPropertyValue(`border-${t}-width`) || n.borderWidth, a = n.getPropertyValue(`border-${t}-color`) || n.borderColor;
|
|
@@ -860,120 +905,150 @@ async function fe(e, t) {
|
|
|
860
905
|
dotted: "dotted",
|
|
861
906
|
double: "double",
|
|
862
907
|
none: "nil"
|
|
863
|
-
}[r] ?? "single"}" w:sz="${Math.max(0, Math.round((
|
|
908
|
+
}[r] ?? "single"}" w:sz="${Math.max(0, Math.round((q(i) ?? .75) * 8))}" w:color="${K(a) ?? "000000"}"/>`;
|
|
864
909
|
}
|
|
865
|
-
function m(e,
|
|
866
|
-
let
|
|
910
|
+
function m(e, n, r) {
|
|
911
|
+
let i = Array.from(e.querySelectorAll("tr")).filter((t) => t.closest("table") === e), a = /* @__PURE__ */ new Map(), o = 1, s = [], c = n.width?.endsWith("%") ? parseFloat(n.width) : void 0, l = Math.max(1, Math.round(J(n.width) ?? (c === void 0 ? r.width : r.width * c / 100))), u = (e) => {
|
|
867
912
|
if (e > 1e3) throw new C("Таблица содержит более 1000 столбцов с учётом объединённых ячеек.");
|
|
868
|
-
},
|
|
869
|
-
let
|
|
913
|
+
}, d = i.map((t) => {
|
|
914
|
+
let r = 0, i = [];
|
|
870
915
|
function c() {
|
|
871
|
-
for (;
|
|
872
|
-
let e =
|
|
873
|
-
|
|
916
|
+
for (; a.has(r);) {
|
|
917
|
+
let e = a.get(r);
|
|
918
|
+
i.push({
|
|
919
|
+
column: r,
|
|
920
|
+
span: e.span,
|
|
921
|
+
rowSpan: 0,
|
|
922
|
+
css: {}
|
|
923
|
+
}), --e.remaining === 0 && a.delete(r), r += e.span, u(r);
|
|
874
924
|
}
|
|
875
925
|
}
|
|
876
|
-
for (let
|
|
926
|
+
for (let o of Array.from(t.children).filter((e) => e.localName === "td" || e.localName === "th")) {
|
|
877
927
|
c();
|
|
878
|
-
let
|
|
879
|
-
|
|
880
|
-
let
|
|
881
|
-
for (;
|
|
882
|
-
let
|
|
883
|
-
...
|
|
928
|
+
let t = Number(o.getAttribute("colspan") || 1), d = Number(o.getAttribute("rowspan") || 1);
|
|
929
|
+
u(r + t);
|
|
930
|
+
let f = [], p = o.parentElement;
|
|
931
|
+
for (; p && p !== e;) f.unshift(p), p = p.parentElement;
|
|
932
|
+
let m = (e) => ({
|
|
933
|
+
...X(e),
|
|
884
934
|
...e["background-color"] ? { "background-color": e["background-color"] } : {}
|
|
885
|
-
}),
|
|
886
|
-
|
|
887
|
-
let g =
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
span:
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
935
|
+
}), h = Y(o, m(f.reduce((e, t) => Y(t, m(e)), n)));
|
|
936
|
+
o.localName === "th" && (h["font-weight"] = "bold");
|
|
937
|
+
let g = J(h.width) ?? (h.width?.endsWith("%") ? parseFloat(h.width) * l / 100 : void 0);
|
|
938
|
+
g !== void 0 && Number.isFinite(g) && g > 0 && s.push({
|
|
939
|
+
column: r,
|
|
940
|
+
span: t,
|
|
941
|
+
width: g
|
|
942
|
+
}), i.push({
|
|
943
|
+
element: o,
|
|
944
|
+
column: r,
|
|
945
|
+
span: t,
|
|
946
|
+
rowSpan: d,
|
|
947
|
+
css: h
|
|
948
|
+
}), d > 1 && a.set(r, {
|
|
949
|
+
remaining: d - 1,
|
|
950
|
+
span: t
|
|
951
|
+
}), r += t;
|
|
952
|
+
}
|
|
953
|
+
for (;;) {
|
|
954
|
+
let e = [...a.keys()].filter((e) => e >= r).sort((e, t) => e - t)[0];
|
|
955
|
+
if (e === void 0) break;
|
|
956
|
+
for (; r < e;) i.push({
|
|
957
|
+
column: r,
|
|
958
|
+
span: 1,
|
|
959
|
+
rowSpan: 1,
|
|
960
|
+
css: {}
|
|
961
|
+
}), r++;
|
|
962
|
+
c();
|
|
911
963
|
}
|
|
912
|
-
return
|
|
913
|
-
})
|
|
964
|
+
return o = Math.max(o, r), i;
|
|
965
|
+
}), f = le(o, l, s, t), m = "<w:p><w:pPr><w:spacing w:before=\"0\" w:after=\"0\"/></w:pPr></w:p>", g = d.map((e) => `<w:tr>${e.map(({ element: e, column: t, span: n, rowSpan: r, css: i }) => {
|
|
966
|
+
let a = f.slice(t, t + n).reduce((e, t) => e + t, 0), o = `<w:tcW w:w="${a}" w:type="dxa"/>`;
|
|
967
|
+
if (n > 1 && (o += `<w:gridSpan w:val="${n}"/>`), r > 1 && (o += "<w:vMerge w:val=\"restart\"/>"), !e) return `<w:tc><w:tcPr>${o}${r === 0 ? "<w:vMerge/>" : ""}</w:tcPr>${m}</w:tc>`;
|
|
968
|
+
let s = K(i["background-color"]);
|
|
969
|
+
s && (o += `<w:shd w:fill="${s}"/>`), [
|
|
970
|
+
"top",
|
|
971
|
+
"middle",
|
|
972
|
+
"bottom"
|
|
973
|
+
].includes(i["vertical-align"]) && (o += `<w:vAlign w:val="${i["vertical-align"] === "middle" ? "center" : i["vertical-align"]}"/>`);
|
|
974
|
+
let c = [
|
|
975
|
+
"top",
|
|
976
|
+
"left",
|
|
977
|
+
"bottom",
|
|
978
|
+
"right"
|
|
979
|
+
], l = c.map((t) => p(e, t)).join("");
|
|
980
|
+
l && (o += `<w:tcBorders>${l}</w:tcBorders>`);
|
|
981
|
+
let u = c.map((e) => J(i[`padding-${e}`]) === void 0 ? "" : `<w:${e} w:w="${Math.max(0, J(i[`padding-${e}`]))}" w:type="dxa"/>`).join("");
|
|
982
|
+
u && (o += `<w:tcMar>${u}</w:tcMar>`);
|
|
983
|
+
let d = Math.max(1, a - Math.max(0, J(i["padding-left"]) ?? 0) - Math.max(0, J(i["padding-right"]) ?? 0)), g = h(e.childNodes, X(i), void 0, {
|
|
984
|
+
width: d,
|
|
985
|
+
cell: !0
|
|
986
|
+
});
|
|
987
|
+
return (!g || g.endsWith("</w:tbl>")) && (g += m), `<w:tc><w:tcPr>${o}</w:tcPr>${g}</w:tc>`;
|
|
988
|
+
}).join("") || `<w:tc>${m}</w:tc>`}</w:tr>`).join(""), _ = f.map((e) => `<w:gridCol w:w="${e}"/>`).join(""), v = c === void 0 ? `<w:tblW w:w="${l}" w:type="dxa"/>` : `<w:tblW w:w="${Math.round(c * 50)}" w:type="pct"/>`, y = [
|
|
914
989
|
"top",
|
|
915
990
|
"left",
|
|
916
991
|
"bottom",
|
|
917
992
|
"right"
|
|
918
|
-
].map((t) => p(e, t)).join("");
|
|
919
|
-
return `<w:tbl><w:tblPr>${
|
|
993
|
+
].map((t) => p(e, t)).join(""), b = n["table-layout"] === "auto" ? "autofit" : "fixed";
|
|
994
|
+
return `<w:tbl><w:tblPr>${v}${y ? `<w:tblBorders>${y}</w:tblBorders>` : ""}<w:tblLayout w:type="${b}"/></w:tblPr><w:tblGrid>${_}</w:tblGrid>${g}</w:tbl>`;
|
|
920
995
|
}
|
|
921
|
-
function h(e, n, a) {
|
|
922
|
-
let
|
|
923
|
-
|
|
996
|
+
function h(e, n, a, o = ue) {
|
|
997
|
+
let s = "", c = [], l = () => {
|
|
998
|
+
c.some((e) => e.nodeType !== 3 || e.textContent?.trim()) && (s += f(c, n, a, o)), c = [];
|
|
924
999
|
};
|
|
925
|
-
for (let
|
|
926
|
-
if (!(
|
|
927
|
-
|
|
1000
|
+
for (let u of e) {
|
|
1001
|
+
if (!(u instanceof Element) || !G.has(u.localName)) {
|
|
1002
|
+
c.push(u);
|
|
928
1003
|
continue;
|
|
929
1004
|
}
|
|
930
|
-
|
|
931
|
-
let e =
|
|
932
|
-
if (
|
|
933
|
-
else if (
|
|
1005
|
+
l();
|
|
1006
|
+
let e = Y(u, X(n));
|
|
1007
|
+
if (u.localName === "table") s += m(u, e, o);
|
|
1008
|
+
else if (u.localName === "ol" || u.localName === "ul") {
|
|
934
1009
|
let n = r++;
|
|
935
1010
|
i.push({
|
|
936
1011
|
id: n,
|
|
937
|
-
tag:
|
|
1012
|
+
tag: u.localName
|
|
938
1013
|
}), a && w(t, "nested-list-normalized", "Вложенный список при открытии становится отдельным списком.", "loss");
|
|
939
|
-
for (let t of Array.from(
|
|
1014
|
+
for (let t of Array.from(u.children)) if (t.localName === "li") {
|
|
940
1015
|
let r = {
|
|
941
1016
|
id: n,
|
|
942
1017
|
pending: !0
|
|
943
1018
|
};
|
|
944
|
-
|
|
1019
|
+
s += h(t.childNodes, Y(t, X(e)), r, o) || f([], e, r, o);
|
|
945
1020
|
}
|
|
946
|
-
} else
|
|
1021
|
+
} else u.localName === "div" && Array.from(u.children).some((e) => G.has(e.localName)) ? (e["page-break-before"] === "always" && (s += f([], {
|
|
947
1022
|
"page-break-before": "always",
|
|
948
1023
|
"margin-bottom": "0pt"
|
|
949
|
-
})),
|
|
1024
|
+
})), s += h(u.childNodes, X(e), a, o), e["page-break-after"] === "always" && (s += f([], {
|
|
950
1025
|
"page-break-before": "always",
|
|
951
1026
|
"margin-bottom": "0pt"
|
|
952
|
-
}))) :
|
|
1027
|
+
}))) : u.localName === "hr" ? (w(t, "rule-normalized", "Разделитель HTML преобразован в строку."), s += f([document.createTextNode("────────────────")], e, void 0, o)) : s += f(u.childNodes, e, a, o);
|
|
953
1028
|
}
|
|
954
|
-
return
|
|
1029
|
+
return l(), s;
|
|
955
1030
|
}
|
|
956
1031
|
let g = h(n.childNodes, c) || "<w:p/>";
|
|
957
1032
|
if (new TextEncoder().encode(g).byteLength > 8387584) throw new C("После преобразования HTML документ превышает допустимый размер XML (8 МиБ).");
|
|
958
1033
|
let _ = new Set("font-family font-size font-weight font-style color background-color text-align text-decoration text-transform vertical-align letter-spacing line-height margin margin-top margin-bottom margin-left margin-right text-indent width border border-style border-width border-color border-top border-right border-bottom border-left border-collapse table-layout padding padding-top padding-right padding-bottom padding-left page-break-before page-break-after page-break-inside".split(" "));
|
|
959
1034
|
for (let e of n.querySelectorAll("[style]")) for (let n of Array.from(e.style)) {
|
|
960
1035
|
let r = e.style.getPropertyValue(n), i = ["td", "th"].includes(e.localName);
|
|
961
|
-
(n.startsWith("padding") && !i || n.startsWith("border") && !i && e.localName !== "table" || n === "font-size" &&
|
|
1036
|
+
(n.startsWith("padding") && !i || n.startsWith("border") && !i && e.localName !== "table" || n === "font-size" && q(r) === void 0 || ["color", "background-color"].includes(n) && K(r) === void 0 || !_.has(n) && !/^border-(top|right|bottom|left)-(width|style|color)$/.test(n)) && w(t, "html-style-approximation", `Стиль ${n} может измениться при открытии HTML в DOCX-редакторе.`);
|
|
962
1037
|
}
|
|
963
1038
|
let v = new d();
|
|
964
|
-
return v.file("[Content_Types].xml", "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/word/document.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\"/><Override PartName=\"/word/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml\"/><Override PartName=\"/word/numbering.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml\"/></Types>"), v.file("_rels/.rels", "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"word/document.xml\"/></Relationships>"), v.file("word/_rels/document.xml.rels", "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rIdStyles\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/><Relationship Id=\"rIdNumbering\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering\" Target=\"numbering.xml\"/></Relationships>"), v.file("word/document.xml", `<w:document xmlns:w="${
|
|
1039
|
+
return v.file("[Content_Types].xml", "<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/word/document.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml\"/><Override PartName=\"/word/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml\"/><Override PartName=\"/word/numbering.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml\"/></Types>"), v.file("_rels/.rels", "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"word/document.xml\"/></Relationships>"), v.file("word/_rels/document.xml.rels", "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rIdStyles\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/><Relationship Id=\"rIdNumbering\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering\" Target=\"numbering.xml\"/></Relationships>"), v.file("word/document.xml", `<w:document xmlns:w="${P}"><w:body>${g}<w:sectPr><w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="850" w:right="1134" w:bottom="1984" w:left="1134" w:header="0" w:footer="0" w:gutter="0"/></w:sectPr></w:body></w:document>`), v.file("word/styles.xml", `<w:styles xmlns:w="${P}"><w:docDefaults><w:rPrDefault><w:rPr>${l(c)}</w:rPr></w:rPrDefault></w:docDefaults><w:style w:type="paragraph" w:default="1" w:styleId="Normal"><w:name w:val="Normal"/><w:pPr><w:spacing w:after="120"/></w:pPr></w:style><w:style w:type="paragraph" w:styleId="AzHujjatListContinuation"><w:name w:val="List continuation"/><w:basedOn w:val="Normal"/></w:style></w:styles>`), v.file("word/numbering.xml", `<w:numbering xmlns:w="${P}">${i.map(({ id: e, tag: t }) => `<w:abstractNum w:abstractNumId="${e}"><w:multiLevelType w:val="singleLevel"/><w:lvl w:ilvl="0"><w:start w:val="1"/><w:numFmt w:val="${t === "ol" ? "decimal" : "bullet"}"/><w:lvlText w:val="${t === "ol" ? "%1." : "•"}"/><w:pPr><w:ind w:left="360" w:hanging="180"/></w:pPr></w:lvl></w:abstractNum><w:num w:numId="${e}"><w:abstractNumId w:val="${e}"/></w:num>`).join("")}</w:numbering>`), new Uint8Array(await v.generateAsync({
|
|
965
1040
|
type: "arraybuffer",
|
|
966
1041
|
compression: "DEFLATE"
|
|
967
1042
|
}));
|
|
968
1043
|
}
|
|
969
1044
|
//#endregion
|
|
970
1045
|
//#region src/library/hujjat/docx.ts
|
|
971
|
-
async function
|
|
972
|
-
let n = await
|
|
1046
|
+
async function me(e, t) {
|
|
1047
|
+
let n = await ce(e), r = ie(t.locales ?? {}, t.locale, n.html);
|
|
973
1048
|
return r.warnings.unshift(...n.warnings), T(r.warnings, t.allowLossy), r;
|
|
974
1049
|
}
|
|
975
|
-
async function
|
|
976
|
-
let r = M(re(e, t)), i = await
|
|
1050
|
+
async function he(e, t, n = {}) {
|
|
1051
|
+
let r = M(re(e, t)), i = await pe(r.html, r.warnings);
|
|
977
1052
|
return T(r.warnings, n.allowLossy), {
|
|
978
1053
|
...r,
|
|
979
1054
|
document: i
|
|
@@ -981,8 +1056,8 @@ async function me(e, t, n = {}) {
|
|
|
981
1056
|
}
|
|
982
1057
|
//#endregion
|
|
983
1058
|
//#region src/library/AzDocumentEditor.tsx
|
|
984
|
-
var
|
|
985
|
-
function
|
|
1059
|
+
var ge = () => {};
|
|
1060
|
+
function _e({ onStatusChange: e }) {
|
|
986
1061
|
let t = c((e) => e.page.total), r = c((e) => e.isLoading || !!e.isOpening), i = c((e) => e.parseError);
|
|
987
1062
|
return n(() => {
|
|
988
1063
|
e?.({
|
|
@@ -997,7 +1072,7 @@ function ge({ onStatusChange: e }) {
|
|
|
997
1072
|
e
|
|
998
1073
|
]), null;
|
|
999
1074
|
}
|
|
1000
|
-
var
|
|
1075
|
+
var ve = e(function(e, t) {
|
|
1001
1076
|
let i = a(null), c = a(null), d = a(null), [h, g] = o(""), _ = l(u()), b = (t) => e.ui !== !1 && e.ui?.[t] !== !1;
|
|
1002
1077
|
function x(e) {
|
|
1003
1078
|
let t = c.current?.querySelector("[data-menu=\"file\"] > [role=\"menuitem\"][aria-expanded=\"true\"]");
|
|
@@ -1031,7 +1106,7 @@ var _e = e(function(e, t) {
|
|
|
1031
1106
|
async exportHujjat(e) {
|
|
1032
1107
|
let t = await i.current?.save();
|
|
1033
1108
|
if (!t) throw new C("Документ ещё не готов к экспорту.");
|
|
1034
|
-
return
|
|
1109
|
+
return me(t, e);
|
|
1035
1110
|
},
|
|
1036
1111
|
insertVariable(e) {
|
|
1037
1112
|
if (!E(e)) throw new C("Некорректный ключ переменной. Используйте client.name, ASCII, до 100 символов.");
|
|
@@ -1079,8 +1154,8 @@ var _e = e(function(e, t) {
|
|
|
1079
1154
|
onFontError: (t) => e.onFontError?.(`Не удалось загрузить шрифт (${t.code}). Переносы могут отличаться от Word.`),
|
|
1080
1155
|
menu: b("menu") && {
|
|
1081
1156
|
reportIssue: !1,
|
|
1082
|
-
onOpen:
|
|
1083
|
-
onSave:
|
|
1157
|
+
onOpen: ge,
|
|
1158
|
+
onSave: ge,
|
|
1084
1159
|
children: /* @__PURE__ */ p(s.Menu.File, {
|
|
1085
1160
|
preset: !1,
|
|
1086
1161
|
children: [
|
|
@@ -1116,18 +1191,18 @@ var _e = e(function(e, t) {
|
|
|
1116
1191
|
]
|
|
1117
1192
|
})
|
|
1118
1193
|
},
|
|
1119
|
-
children: /* @__PURE__ */ f(
|
|
1194
|
+
children: /* @__PURE__ */ f(_e, { onStatusChange: e.onStatusChange })
|
|
1120
1195
|
})]
|
|
1121
1196
|
});
|
|
1122
1197
|
});
|
|
1123
1198
|
//#endregion
|
|
1124
1199
|
//#region src/library/AzHtmlEditor.tsx
|
|
1125
|
-
function
|
|
1200
|
+
function ye(...e) {
|
|
1126
1201
|
let t = /* @__PURE__ */ new Map();
|
|
1127
1202
|
for (let n of e.flat()) t.set(JSON.stringify(n), n);
|
|
1128
1203
|
return [...t.values()];
|
|
1129
1204
|
}
|
|
1130
|
-
var
|
|
1205
|
+
var be = e(function(e, s) {
|
|
1131
1206
|
let { initialHtml: c, onChange: l, onStatusChange: u, renderFallback: d, ...m } = e, [h] = o(c), [g, _] = o(), [v, y] = o({
|
|
1132
1207
|
phase: "loading",
|
|
1133
1208
|
dirty: !1,
|
|
@@ -1150,7 +1225,7 @@ var ye = e(function(e, s) {
|
|
|
1150
1225
|
error: null
|
|
1151
1226
|
});
|
|
1152
1227
|
try {
|
|
1153
|
-
let n = await
|
|
1228
|
+
let n = await he({ uz: { blocks: [{
|
|
1154
1229
|
type: "html",
|
|
1155
1230
|
props: { html: h.trim() ? h : "<p><br></p>" }
|
|
1156
1231
|
}] } }, "uz", { allowLossy: e });
|
|
@@ -1202,7 +1277,7 @@ var ye = e(function(e, s) {
|
|
|
1202
1277
|
allowLossy: !0
|
|
1203
1278
|
});
|
|
1204
1279
|
if (!w.current || n !== E.current || r !== D.current) throw new C("Черновик изменился или закрыт во время экспорта. Повторите экспорт актуального документа.");
|
|
1205
|
-
let a =
|
|
1280
|
+
let a = ye(t.warnings, i.warnings);
|
|
1206
1281
|
return k({ warnings: a }), T(a, e.allowLossy), {
|
|
1207
1282
|
html: i.html,
|
|
1208
1283
|
variables: i.variables,
|
|
@@ -1229,7 +1304,7 @@ var ye = e(function(e, s) {
|
|
|
1229
1304
|
A,
|
|
1230
1305
|
k,
|
|
1231
1306
|
j
|
|
1232
|
-
]), g ? /* @__PURE__ */ f(
|
|
1307
|
+
]), g ? /* @__PURE__ */ f(ve, {
|
|
1233
1308
|
...m,
|
|
1234
1309
|
ref: x,
|
|
1235
1310
|
document: g,
|
|
@@ -1250,7 +1325,7 @@ var ye = e(function(e, s) {
|
|
|
1250
1325
|
children: [v.error ?? "Загрузка документа…", v.warnings.length > 0 && /* @__PURE__ */ f("ul", { children: v.warnings.map((e, t) => /* @__PURE__ */ f("li", { children: e.message }, t)) })]
|
|
1251
1326
|
})
|
|
1252
1327
|
});
|
|
1253
|
-
}),
|
|
1328
|
+
}), xe = 31457280, Se = "application/vnd.openxmlformats-officedocument.wordprocessingml.document", Ce = `${Se}.main+xml`, we = 8388608, Z = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
1254
1329
|
function Q(e) {
|
|
1255
1330
|
let t = new DOMParser().parseFromString(e, "application/xml");
|
|
1256
1331
|
if (t.getElementsByTagName("parsererror").length || /<!DOCTYPE/i.test(e)) throw Error("XML документа повреждён или содержит неподдерживаемую структуру.");
|
|
@@ -1261,7 +1336,7 @@ function $(e, t) {
|
|
|
1261
1336
|
return n ? new Promise((e, t) => {
|
|
1262
1337
|
let r = n.internalStream("uint8array"), i = [], a = 0;
|
|
1263
1338
|
r.on("data", (e) => {
|
|
1264
|
-
a += e.byteLength, a >
|
|
1339
|
+
a += e.byteLength, a > we ? (r.pause(), t(/* @__PURE__ */ Error("Структура документа слишком большая для этого прототипа."))) : i.push(e);
|
|
1265
1340
|
}), r.on("error", t), r.on("end", () => {
|
|
1266
1341
|
let t = new Uint8Array(a), n = 0;
|
|
1267
1342
|
for (let e of i) t.set(e, n), n += e.byteLength;
|
|
@@ -1269,7 +1344,7 @@ function $(e, t) {
|
|
|
1269
1344
|
}), r.resume();
|
|
1270
1345
|
}) : Promise.resolve("");
|
|
1271
1346
|
}
|
|
1272
|
-
async function
|
|
1347
|
+
async function Te(e) {
|
|
1273
1348
|
if (!/\.docx$/i.test(e.name)) throw Error("Откройте файл DOCX. Форматы DOC, DOCM и PDF здесь не поддерживаются.");
|
|
1274
1349
|
if (!e.size) throw Error("Файл DOCX пуст.");
|
|
1275
1350
|
if (e.size > 31457280) throw Error("Максимальный размер DOCX — 30 МБ.");
|
|
@@ -1283,7 +1358,7 @@ async function Ce(e) {
|
|
|
1283
1358
|
if (r.length > 2e3) throw Error("Слишком много вложенных частей в DOCX для этого прототипа.");
|
|
1284
1359
|
if (!n.file("[Content_Types].xml") || !n.file("word/document.xml")) throw Error("Файл не содержит структуру DOCX.");
|
|
1285
1360
|
let i = Q(await $(n, "[Content_Types].xml"));
|
|
1286
|
-
if (Array.from(i.getElementsByTagNameNS("*", "Override")).find((e) => e.getAttribute("PartName") === "/word/document.xml")?.getAttribute("ContentType") !==
|
|
1361
|
+
if (Array.from(i.getElementsByTagNameNS("*", "Override")).find((e) => e.getAttribute("PartName") === "/word/document.xml")?.getAttribute("ContentType") !== Ce || r.some((e) => /vbaProject\.bin$/i.test(e))) throw Error("Поддерживается только обычный DOCX без макросов.");
|
|
1287
1362
|
let a = Q(await $(n, "word/document.xml"));
|
|
1288
1363
|
if (a.documentElement.localName !== "document" || !a.getElementsByTagNameNS(Z, "body").length) throw Error("XML документа повреждён или использует неподдерживаемую разновидность DOCX.");
|
|
1289
1364
|
let o = /* @__PURE__ */ new Set(), s = [a];
|
|
@@ -1323,16 +1398,16 @@ async function Ce(e) {
|
|
|
1323
1398
|
}
|
|
1324
1399
|
};
|
|
1325
1400
|
}
|
|
1326
|
-
function
|
|
1401
|
+
function Ee(e) {
|
|
1327
1402
|
return `${(e.replace(/\.docx$/i, "").replace(/[<>:"/\\|?*\x00-\x1f]/g, "_").trim() || "Документ").replace(/ — редакция$/, "")} — редакция.docx`;
|
|
1328
1403
|
}
|
|
1329
|
-
function
|
|
1330
|
-
let n = URL.createObjectURL(new Blob([e], { type:
|
|
1404
|
+
function De(e, t) {
|
|
1405
|
+
let n = URL.createObjectURL(new Blob([e], { type: Se })), r = document.createElement("a");
|
|
1331
1406
|
r.href = n, r.download = t, document.body.append(r), r.click(), r.remove(), window.setTimeout(() => URL.revokeObjectURL(n), 3e4);
|
|
1332
1407
|
}
|
|
1333
1408
|
//#endregion
|
|
1334
1409
|
//#region src/library/pdf-export.ts
|
|
1335
|
-
async function
|
|
1410
|
+
async function Oe(e, t, n, r = {}) {
|
|
1336
1411
|
let i = AbortSignal.any([AbortSignal.timeout(95e3), ...r.signal ? [r.signal] : []]);
|
|
1337
1412
|
i.throwIfAborted();
|
|
1338
1413
|
let a = new FormData();
|
|
@@ -1361,13 +1436,13 @@ async function Ee(e, t, n, r = {}) {
|
|
|
1361
1436
|
warnings: (o.headers.get("x-pdf-warnings") ?? "").split(",").filter(Boolean)
|
|
1362
1437
|
};
|
|
1363
1438
|
}
|
|
1364
|
-
function
|
|
1439
|
+
function ke(e) {
|
|
1365
1440
|
let t = URL.createObjectURL(e.blob), n = document.createElement("a");
|
|
1366
1441
|
n.href = t, n.download = e.filename, document.body.append(n), n.click(), n.remove(), setTimeout(() => URL.revokeObjectURL(t), 6e4);
|
|
1367
1442
|
}
|
|
1368
1443
|
//#endregion
|
|
1369
1444
|
//#region src/library/pdf-profile.ts
|
|
1370
|
-
var
|
|
1445
|
+
var Ae = {
|
|
1371
1446
|
id: "az-editor-pdf-a0c6eaaeb90716f0",
|
|
1372
1447
|
protocolVersion: 1,
|
|
1373
1448
|
core: "2.27.0",
|
|
@@ -1514,7 +1589,7 @@ var Oe = {
|
|
|
1514
1589
|
};
|
|
1515
1590
|
//#endregion
|
|
1516
1591
|
//#region src/library/hujjat/api.ts
|
|
1517
|
-
function
|
|
1592
|
+
function je(e) {
|
|
1518
1593
|
if (!e || !Object.keys(e).length) throw new C("Нет локалей шаблона.");
|
|
1519
1594
|
for (let [t, n] of Object.entries(e)) {
|
|
1520
1595
|
if (N(t), !n || !Array.isArray(n.blocks) || !n.blocks.length) throw new C(`Нет блоков для ${t}.`);
|
|
@@ -1524,8 +1599,8 @@ function ke(e) {
|
|
|
1524
1599
|
}
|
|
1525
1600
|
}
|
|
1526
1601
|
}
|
|
1527
|
-
function
|
|
1528
|
-
if (
|
|
1602
|
+
function Me(e, t) {
|
|
1603
|
+
if (je(t), !t.uz) throw new C("Для создания шаблона обязательна локаль uz.");
|
|
1529
1604
|
if (!e.productId || !e.name.trim() || e.name.length > 255) throw new C("Укажите продукт и название шаблона до 255 символов.");
|
|
1530
1605
|
return {
|
|
1531
1606
|
product_id: e.productId,
|
|
@@ -1534,9 +1609,9 @@ function Ae(e, t) {
|
|
|
1534
1609
|
locales: structuredClone(t)
|
|
1535
1610
|
};
|
|
1536
1611
|
}
|
|
1537
|
-
async function
|
|
1612
|
+
async function Ne(e) {
|
|
1538
1613
|
let t = AbortSignal.any([AbortSignal.timeout(95e3), ...e.signal ? [e.signal] : []]);
|
|
1539
|
-
t.throwIfAborted(),
|
|
1614
|
+
t.throwIfAborted(), je(e.locales);
|
|
1540
1615
|
let n = e.locale ?? "uz";
|
|
1541
1616
|
N(n);
|
|
1542
1617
|
let r = new Headers(e.headers);
|
|
@@ -1566,4 +1641,4 @@ async function je(e) {
|
|
|
1566
1641
|
};
|
|
1567
1642
|
}
|
|
1568
1643
|
//#endregion
|
|
1569
|
-
export {
|
|
1644
|
+
export { ve as AzDocumentEditor, be as AzHtmlEditor, Se as DOCX_MIME, b as HUJJAT_LOCALES, x as HUJJAT_MAX_HTML_BYTES, S as HUJJAT_PAGE, C as HujjatCompatibilityError, xe as MAX_DOCX_BYTES, Me as createHujjatTemplatePayload, De as downloadDocx, ke as downloadPdf, Ee as exportFilename, me as exportHujjatDocx, he as importHujjatTemplate, Ae as pdfRenderProfile, Te as readDocxFile, re as readHujjatHtml, Ne as requestHujjatPreview, Oe as requestPdf, M as sanitizeHujjatHtml, E as validateHujjatVariable, ie as withHujjatLocale };
|