@makhmudov.kay/az-editor 0.1.0-beta.2 → 0.1.0-beta.4
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/CHANGELOG.md +27 -0
- package/README.md +73 -70
- package/dist/az-editor.js +1029 -500
- package/dist/library/AzDocumentEditor.d.ts +13 -1
- package/dist/library/AzHtmlEditor.d.ts +7 -1
- package/dist/library/document-diagnostics.d.ts +3 -0
- package/dist/library/font-diagnostics.d.ts +16 -0
- package/dist/library/hujjat/contract.d.ts +15 -9
- package/dist/library/hujjat/docx-to-html.d.ts +3 -1
- package/dist/library/hujjat/docx.d.ts +6 -3
- package/dist/library/hujjat/html-to-docx.d.ts +2 -1
- package/dist/library/hujjat/page-layout.d.ts +5 -0
- package/dist/library/hujjat/paragraph-format.d.ts +10 -0
- package/dist/library/hujjat/table-grid.d.ts +8 -0
- package/dist/library/index.d.ts +6 -1
- package/dist/library/layout-profile.d.ts +37 -0
- package/docs/integration.ru.md +911 -875
- package/docs/layout-metadata-v1.ru.md +135 -0
- package/examples/integration/DocxEditorExample.tsx +7 -2
- package/examples/integration/HtmlDraft.tsx +1 -0
- package/examples/integration/LayoutDraftExample.tsx +39 -0
- package/examples/integration/README.md +1 -0
- package/package.json +4 -1
package/dist/az-editor.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { forwardRef as e, useCallback as t, useEffect as n, useImperativeHandle as r, useLayoutEffect as i,
|
|
2
|
-
import { DocxEditor as
|
|
3
|
-
import { packagedFonts as
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
1
|
+
import { forwardRef as e, useCallback as t, useEffect as n, useImperativeHandle as r, useLayoutEffect as i, useMemo as a, useRef as o, useState as s, useSyncExternalStore as c } from "react";
|
|
2
|
+
import { DocxEditor as l, useEditorState as u, useFonts as d } from "@docx-editor.dev/react";
|
|
3
|
+
import { packagedFonts as f } from "@docx-editor.dev/fonts";
|
|
4
|
+
import p from "jszip";
|
|
5
|
+
import { defineFontResolver as m } from "@docx-editor.dev/core/editor";
|
|
6
|
+
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
6
7
|
//#region src/library/ru.ts
|
|
7
|
-
var
|
|
8
|
+
var _ = {
|
|
8
9
|
common: {
|
|
9
10
|
cancel: "Отмена",
|
|
10
11
|
apply: "Применить",
|
|
@@ -128,13 +129,13 @@ var m = {
|
|
|
128
129
|
blockSpacingRules: "Интервалы абзаца",
|
|
129
130
|
options: "Параметры интервалов…"
|
|
130
131
|
}
|
|
131
|
-
},
|
|
132
|
+
}, v = class extends Error {
|
|
132
133
|
code;
|
|
133
134
|
constructor(e) {
|
|
134
135
|
super(e), this.code = e;
|
|
135
136
|
}
|
|
136
137
|
};
|
|
137
|
-
function
|
|
138
|
+
function y(e) {
|
|
138
139
|
return e.throwIfAborted(), new Promise((t, n) => {
|
|
139
140
|
let r = () => {
|
|
140
141
|
cancelAnimationFrame(i), n(e.reason);
|
|
@@ -144,7 +145,7 @@ function g(e) {
|
|
|
144
145
|
e.addEventListener("abort", r, { once: !0 });
|
|
145
146
|
});
|
|
146
147
|
}
|
|
147
|
-
async function
|
|
148
|
+
async function b(e, t, n, r, i, a = Infinity) {
|
|
148
149
|
let o = t.ownerDocument, s = e.getZoom(), c = e.getZoomMode(), l = e.getCurrentPage("viewport"), u = Array.from(t.querySelectorAll("*")).filter((e) => e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth).map((e) => ({
|
|
149
150
|
el: e,
|
|
150
151
|
top: e.scrollTop,
|
|
@@ -162,9 +163,9 @@ async function _(e, t, n, r, i, a = Infinity) {
|
|
|
162
163
|
async function m() {
|
|
163
164
|
let t = p(), n = 0;
|
|
164
165
|
for (; n < 2;) {
|
|
165
|
-
await
|
|
166
|
+
await y(i);
|
|
166
167
|
let r = e.snapshot();
|
|
167
|
-
if (r.parseError) throw new
|
|
168
|
+
if (r.parseError) throw new v("INVALID_DOCX");
|
|
168
169
|
let a = p();
|
|
169
170
|
n = !r.isLoading && !r.isOpening && a === t ? n + 1 : 0, t = a;
|
|
170
171
|
}
|
|
@@ -172,24 +173,24 @@ async function _(e, t, n, r, i, a = Infinity) {
|
|
|
172
173
|
try {
|
|
173
174
|
i.throwIfAborted(), await e.save(), await o.fonts.ready, i.throwIfAborted(), e.setZoom(1), await m();
|
|
174
175
|
let s = e.snapshot().page.total;
|
|
175
|
-
if (s > a) throw new
|
|
176
|
-
if (!s) throw new
|
|
176
|
+
if (s > a) throw new v("PAGE_LIMIT_EXCEEDED");
|
|
177
|
+
if (!s) throw new v("RENDER_FAILED");
|
|
177
178
|
let c = e.getDocumentHandle?.().revision, l = [], u = [];
|
|
178
179
|
n.replaceChildren();
|
|
179
180
|
for (let r = 0; r < s; r++) {
|
|
180
181
|
i.throwIfAborted(), e.scrollToPage(r + 1), await m();
|
|
181
182
|
let a = t.querySelector(`.docx-page[data-page-index="${r}"]`);
|
|
182
|
-
if (!a || a.dataset.materialized !== "true") throw new
|
|
183
|
+
if (!a || a.dataset.materialized !== "true") throw new v("RENDER_FAILED");
|
|
183
184
|
await Promise.all(Array.from(a.querySelectorAll("img")).map((e) => e.decode())), await o.fonts.ready, await m();
|
|
184
185
|
let s = Number.parseFloat(a.style.width), c = Number.parseFloat(a.style.height);
|
|
185
|
-
if (!Number.isFinite(s) || !Number.isFinite(c) || s <= 0 || c <= 0) throw new
|
|
186
|
+
if (!Number.isFinite(s) || !Number.isFinite(c) || s <= 0 || c <= 0) throw new v("RENDER_FAILED");
|
|
186
187
|
let d = a.cloneNode(!0);
|
|
187
188
|
d.classList.add("az-print-sheet"), d.removeAttribute("contenteditable"), d.removeAttribute("aria-hidden"), d.querySelectorAll("[contenteditable]").forEach((e) => e.removeAttribute("contenteditable")), d.querySelectorAll("[data-docx-hf-label]").forEach((e) => e.remove()), d.style.setProperty("page", `az-sheet-${r}`), l.push({
|
|
188
189
|
widthPt: s * 72 / 96,
|
|
189
190
|
heightPt: c * 72 / 96
|
|
190
191
|
}), u.push(`@page az-sheet-${r} { size: ${(s * .75).toFixed(3)}pt ${(c * .75).toFixed(3)}pt; margin: 0; }`), n.append(d);
|
|
191
192
|
}
|
|
192
|
-
if (r.textContent = u.join("\n"), await Promise.all(Array.from(n.querySelectorAll("img")).map((e) => e.decode())), await o.fonts.ready, await m(), e.snapshot().page.total !== s || e.getDocumentHandle?.().revision !== c || n.children.length !== s) throw new
|
|
193
|
+
if (r.textContent = u.join("\n"), await Promise.all(Array.from(n.querySelectorAll("img")).map((e) => e.decode())), await o.fonts.ready, await m(), e.snapshot().page.total !== s || e.getDocumentHandle?.().revision !== c || n.children.length !== s) throw new v("RENDER_FAILED");
|
|
193
194
|
return l;
|
|
194
195
|
} catch (e) {
|
|
195
196
|
throw n.replaceChildren(), r.textContent = "", e;
|
|
@@ -201,11 +202,11 @@ async function _(e, t, n, r, i, a = Infinity) {
|
|
|
201
202
|
}
|
|
202
203
|
//#endregion
|
|
203
204
|
//#region src/library/print-document.ts
|
|
204
|
-
function
|
|
205
|
+
function x(e, t) {
|
|
205
206
|
let n = e.ownerDocument;
|
|
206
207
|
return ((t instanceof Element ? t.closest(".az-document-editor") : null) ?? n.activeElement?.closest(".az-document-editor")) === e;
|
|
207
208
|
}
|
|
208
|
-
async function
|
|
209
|
+
async function S(e, t, n, r) {
|
|
209
210
|
let i = t.ownerDocument, a = i.defaultView, o = i.title, s = i.activeElement instanceof HTMLElement ? i.activeElement : null, c = e.getZoom(), l = e.getZoomMode(), u = e.getCurrentPage("viewport"), d = Array.from(t.querySelectorAll("*")).filter((e) => e.scrollHeight > e.clientHeight || e.scrollWidth > e.clientWidth).map((e) => ({
|
|
210
211
|
el: e,
|
|
211
212
|
top: e.scrollTop,
|
|
@@ -222,9 +223,9 @@ async function y(e, t, n, r) {
|
|
|
222
223
|
};
|
|
223
224
|
let g = i.createElement("button");
|
|
224
225
|
g.textContent = "Вернуться к редактированию";
|
|
225
|
-
let
|
|
226
|
-
|
|
227
|
-
let
|
|
226
|
+
let _ = i.createElement("div");
|
|
227
|
+
_.className = "az-print-pages";
|
|
228
|
+
let v = i.createElement("style"), y = Array.from(i.body.children).filter((e) => e instanceof HTMLElement).map((e) => ({
|
|
228
229
|
el: e,
|
|
229
230
|
inert: e.inert
|
|
230
231
|
})), x = new AbortController(), S = AbortSignal.any([r, x.signal]), C = !1, w = !1, T = () => {
|
|
@@ -232,13 +233,13 @@ async function y(e, t, n, r) {
|
|
|
232
233
|
e.scrollTop = t, e.scrollLeft = n;
|
|
233
234
|
})));
|
|
234
235
|
}, E = () => {
|
|
235
|
-
C || (C = !0, x.abort(), T(), f.remove(), i.title = o,
|
|
236
|
+
C || (C = !0, x.abort(), T(), f.remove(), i.title = o, y.forEach(({ el: e, inert: t }) => {
|
|
236
237
|
e.inert = t;
|
|
237
238
|
}), r.removeEventListener("abort", E), s?.focus({ preventScroll: !0 }));
|
|
238
239
|
};
|
|
239
240
|
g.onclick = E, f.onkeydown = (e) => {
|
|
240
241
|
e.key === "Escape" && (e.preventDefault(), E()), (e.ctrlKey || e.metaKey) && e.code === "KeyP" && (e.preventDefault(), e.stopPropagation(), h.disabled || h.click()), e.key === "Tab" && (e.preventDefault(), i.activeElement === h || h.disabled ? g.focus() : h.focus());
|
|
241
|
-
}, p.append(m, h, g), f.append(p,
|
|
242
|
+
}, p.append(m, h, g), f.append(p, _, v), i.body.append(f), y.forEach(({ el: e }) => {
|
|
242
243
|
e.inert = !0;
|
|
243
244
|
}), g.focus(), r.addEventListener("abort", E, { once: !0 });
|
|
244
245
|
let D = () => {
|
|
@@ -246,7 +247,7 @@ async function y(e, t, n, r) {
|
|
|
246
247
|
};
|
|
247
248
|
try {
|
|
248
249
|
D(), w = !0;
|
|
249
|
-
let n = (await
|
|
250
|
+
let n = (await b(e, t, _, v, S)).length;
|
|
250
251
|
return D(), m.textContent = `Страниц: ${n}. В диалоге печати выберите «Сохранить как PDF». Масштаб — 100%, поля — нет, колонтитулы браузера — выключены.`, h.disabled = !1, h.focus(), E;
|
|
251
252
|
} catch (e) {
|
|
252
253
|
throw E(), e;
|
|
@@ -255,46 +256,111 @@ async function y(e, t, n, r) {
|
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
258
|
//#endregion
|
|
258
|
-
//#region src/library/
|
|
259
|
-
var
|
|
260
|
-
"uz",
|
|
261
|
-
"ru",
|
|
262
|
-
"uz_cyrl",
|
|
263
|
-
"en"
|
|
264
|
-
], x = 1048576, S = {
|
|
259
|
+
//#region src/library/layout-profile.ts
|
|
260
|
+
var C = Object.freeze({
|
|
265
261
|
widthMm: 210,
|
|
266
262
|
heightMm: 297,
|
|
267
263
|
topMm: 15,
|
|
268
264
|
rightMm: 20,
|
|
269
265
|
bottomMm: 35,
|
|
270
266
|
leftMm: 20
|
|
271
|
-
},
|
|
267
|
+
}), w = (e) => Math.round(e * 1440 / 25.4);
|
|
268
|
+
function T(e) {
|
|
269
|
+
return e.widthTwips - e.margins.left - e.margins.right - e.margins.gutter;
|
|
270
|
+
}
|
|
271
|
+
function E(e = {}) {
|
|
272
|
+
let t = e.page ?? {
|
|
273
|
+
widthTwips: w(C.widthMm),
|
|
274
|
+
heightTwips: w(C.heightMm),
|
|
275
|
+
orientation: "portrait",
|
|
276
|
+
margins: {
|
|
277
|
+
top: w(C.topMm),
|
|
278
|
+
right: w(C.rightMm),
|
|
279
|
+
bottom: w(C.bottomMm),
|
|
280
|
+
left: w(C.leftMm),
|
|
281
|
+
header: 0,
|
|
282
|
+
footer: 0,
|
|
283
|
+
gutter: 0
|
|
284
|
+
}
|
|
285
|
+
}, n = {
|
|
286
|
+
widthTwips: t.widthTwips,
|
|
287
|
+
heightTwips: t.heightTwips,
|
|
288
|
+
orientation: t.orientation,
|
|
289
|
+
margins: Object.fromEntries([
|
|
290
|
+
"top",
|
|
291
|
+
"right",
|
|
292
|
+
"bottom",
|
|
293
|
+
"left",
|
|
294
|
+
"header",
|
|
295
|
+
"footer",
|
|
296
|
+
"gutter"
|
|
297
|
+
].map((e) => [e, t.margins?.[e]]))
|
|
298
|
+
}, r = (e) => Number.isSafeInteger(e) && e > 0 && e <= 31680;
|
|
299
|
+
if (!r(n.widthTwips) || !r(n.heightTwips) || !["portrait", "landscape"].includes(n.orientation) || (n.orientation === "portrait" ? n.widthTwips > n.heightTwips : n.heightTwips > n.widthTwips) || [
|
|
300
|
+
"top",
|
|
301
|
+
"right",
|
|
302
|
+
"bottom",
|
|
303
|
+
"left",
|
|
304
|
+
"header",
|
|
305
|
+
"footer",
|
|
306
|
+
"gutter"
|
|
307
|
+
].some((e) => {
|
|
308
|
+
let t = n.margins[e];
|
|
309
|
+
return !Number.isSafeInteger(t) || t < 0 || t > 31680;
|
|
310
|
+
}) || T(n) <= 0 || n.heightTwips - n.margins.top - n.margins.bottom <= 0) throw RangeError("Некорректная геометрия страницы: нужны целые twips, согласованная ориентация и положительная область текста (размеры до 22 дюймов).");
|
|
311
|
+
let i = e.lineSpacingPolicy ?? "normalize";
|
|
312
|
+
if (!["normalize", "preserve"].includes(i)) throw TypeError("Неизвестная политика межстрочного интервала.");
|
|
313
|
+
return {
|
|
314
|
+
schema: "az-editor.layout",
|
|
315
|
+
version: 1,
|
|
316
|
+
page: n,
|
|
317
|
+
lineSpacingPolicy: i
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
function D(e, t) {
|
|
321
|
+
return e.widthTwips === t.widthTwips && e.heightTwips === t.heightTwips && e.orientation === t.orientation && Object.keys(e.margins).every((n) => e.margins[n] === t.margins[n]);
|
|
322
|
+
}
|
|
323
|
+
//#endregion
|
|
324
|
+
//#region src/library/hujjat/contract.ts
|
|
325
|
+
var O = [
|
|
326
|
+
"uz",
|
|
327
|
+
"ru",
|
|
328
|
+
"uz_cyrl",
|
|
329
|
+
"en"
|
|
330
|
+
], k = 1048576, A = class extends Error {
|
|
272
331
|
warnings;
|
|
273
332
|
constructor(e, t = []) {
|
|
274
333
|
super(e), this.name = "HujjatCompatibilityError", this.warnings = t;
|
|
275
334
|
}
|
|
276
|
-
};
|
|
277
|
-
function
|
|
278
|
-
|
|
335
|
+
}, j = /* @__PURE__ */ new WeakMap();
|
|
336
|
+
function M(e, t, n, r = "warning", i = {}) {
|
|
337
|
+
let a = {
|
|
279
338
|
code: t,
|
|
280
339
|
message: n,
|
|
281
|
-
severity: r
|
|
282
|
-
|
|
340
|
+
severity: r,
|
|
341
|
+
...i
|
|
342
|
+
}, o = j.get(e);
|
|
343
|
+
(!o || o.length !== e.length) && (o = {
|
|
344
|
+
length: e.length,
|
|
345
|
+
keys: new Set(e.map((e) => JSON.stringify(e)))
|
|
346
|
+
}, j.set(e, o));
|
|
347
|
+
let s = JSON.stringify(a);
|
|
348
|
+
o.keys.has(s) || (e.push(a), o.keys.add(s), o.length = e.length);
|
|
283
349
|
}
|
|
284
|
-
function
|
|
285
|
-
if (!t && e.some((e) => e.severity === "loss")) throw new
|
|
350
|
+
function N(e, t = !1) {
|
|
351
|
+
if (!t && e.some((e) => e.severity === "loss")) throw new A("Hujjat не сохраняет часть содержимого. Проверьте warnings; allowLossy разрешает экспорт с указанными потерями.", e);
|
|
286
352
|
}
|
|
287
|
-
function
|
|
353
|
+
function P(e) {
|
|
288
354
|
return e.length <= 100 && /^[A-Za-z0-9_]+(?:\.[A-Za-z0-9_]+)*$/.test(e) && !e.split(".").some((e) => [
|
|
289
355
|
"__proto__",
|
|
290
356
|
"prototype",
|
|
291
357
|
"constructor"
|
|
292
358
|
].includes(e));
|
|
293
359
|
}
|
|
294
|
-
function
|
|
360
|
+
function F(e) {
|
|
295
361
|
return /courier|mono/i.test(e) ? "freemono" : /arial|helvetica|calibri|sans/i.test(e) ? "freesans" : "freeserif";
|
|
296
362
|
}
|
|
297
|
-
var
|
|
363
|
+
var I = new Set("div p span br hr b strong i em u s sub sup h1 h2 h3 h4 h5 h6 ul ol li table thead tbody tfoot tr td th".split(" ")), ee = new Set("script style iframe object embed svg math img picture video audio canvas link meta form input textarea select button template noscript base frame frameset".split(" ")), te = new Set("div p h1 h2 h3 h4 h5 h6 ul ol li table thead tbody tfoot tr td th br hr".split(" ")), ne = new Set(("color font-family font-size font-weight font-style text-decoration text-align text-transform text-indent letter-spacing line-height white-space vertical-align background background-color width height margin padding border border-color border-width border-style border-collapse table-layout page-break-before page-break-after page-break-inside " + [
|
|
298
364
|
"top",
|
|
299
365
|
"right",
|
|
300
366
|
"bottom",
|
|
@@ -307,7 +373,7 @@ var O = new Set("div p span br hr b strong i em u s sub sup h1 h2 h3 h4 h5 h6 ul
|
|
|
307
373
|
`border-${e}-width`,
|
|
308
374
|
`border-${e}-color`
|
|
309
375
|
]).join(" ")).split(" "));
|
|
310
|
-
function
|
|
376
|
+
function re(e, t) {
|
|
311
377
|
let n = /* @__PURE__ */ new Map();
|
|
312
378
|
for (let r of e.split(";")) {
|
|
313
379
|
if (!r.trim()) continue;
|
|
@@ -319,22 +385,22 @@ function te(e, t) {
|
|
|
319
385
|
mm: 72 / 25.4,
|
|
320
386
|
pc: 12
|
|
321
387
|
}[e[2].toLowerCase()] > 600);
|
|
322
|
-
if (e < 1 || !
|
|
388
|
+
if (e < 1 || !ne.has(i) || !a || o || s || i === "color" && a.toLowerCase() === "auto") M(t, "css-removed", `Стиль ${i || r} не поддерживается контрактом Hujjat.`);
|
|
323
389
|
else {
|
|
324
390
|
if (i === "font-family") {
|
|
325
|
-
let e =
|
|
326
|
-
a.replace(/['"]/g, "").toLowerCase() !== e &&
|
|
391
|
+
let e = F(a);
|
|
392
|
+
a.replace(/['"]/g, "").toLowerCase() !== e && M(t, "font-substitution", `Шрифт ${a} заменён на ${e}.`), a = e;
|
|
327
393
|
}
|
|
328
394
|
n.set(i, a);
|
|
329
395
|
}
|
|
330
396
|
}
|
|
331
397
|
return [...n].map(([e, t]) => `${e}:${t}`).join(";");
|
|
332
398
|
}
|
|
333
|
-
function
|
|
399
|
+
function ie(e) {
|
|
334
400
|
let t = document.createElement("template");
|
|
335
401
|
return t.innerHTML = e, t.content;
|
|
336
402
|
}
|
|
337
|
-
function
|
|
403
|
+
function ae(e) {
|
|
338
404
|
let t = [], n = [], r = () => {
|
|
339
405
|
n.length && t.push(n), n = [];
|
|
340
406
|
};
|
|
@@ -343,7 +409,7 @@ function ne(e) {
|
|
|
343
409
|
n.push(e);
|
|
344
410
|
return;
|
|
345
411
|
}
|
|
346
|
-
let t = e instanceof Element &&
|
|
412
|
+
let t = e instanceof Element && te.has(e.localName);
|
|
347
413
|
t && r();
|
|
348
414
|
for (let t of e.childNodes) i(t);
|
|
349
415
|
t && r();
|
|
@@ -368,30 +434,30 @@ function ne(e) {
|
|
|
368
434
|
}
|
|
369
435
|
}
|
|
370
436
|
}
|
|
371
|
-
function
|
|
372
|
-
if (typeof e != "string" || !e.trim()) throw new
|
|
373
|
-
if (new TextEncoder().encode(e).length > 1048576) throw new
|
|
374
|
-
let t =
|
|
437
|
+
function oe(e) {
|
|
438
|
+
if (typeof e != "string" || !e.trim()) throw new A("HTML шаблона пуст.");
|
|
439
|
+
if (new TextEncoder().encode(e).length > 1048576) throw new A("HTML превышает 1 МБ (1048576 байт).");
|
|
440
|
+
let t = ie(e), n = document.createElement("div"), r = [], i = 0;
|
|
375
441
|
function a(e, t, n) {
|
|
376
|
-
if (++i > 5e4 || n > 100) throw new
|
|
442
|
+
if (++i > 5e4 || n > 100) throw new A("HTML слишком сложный.");
|
|
377
443
|
if (e.nodeType === 3) {
|
|
378
444
|
t.appendChild(document.createTextNode(e.textContent ?? ""));
|
|
379
445
|
return;
|
|
380
446
|
}
|
|
381
447
|
if (!(e instanceof Element)) return;
|
|
382
448
|
let o = e.localName.toLowerCase();
|
|
383
|
-
if (
|
|
384
|
-
|
|
449
|
+
if (ee.has(o)) {
|
|
450
|
+
M(r, "html-element-removed", `Элемент ${o} удалён: он не поддерживается HTML-блоком Hujjat.`, "loss");
|
|
385
451
|
return;
|
|
386
452
|
}
|
|
387
|
-
if (!
|
|
388
|
-
|
|
453
|
+
if (!I.has(o)) {
|
|
454
|
+
M(r, "html-tag-unwrapped", `Тег ${o} удалён с сохранением текста.`);
|
|
389
455
|
for (let r of e.childNodes) a(r, t, n + 1);
|
|
390
456
|
return;
|
|
391
457
|
}
|
|
392
458
|
let s = document.createElement(o), c = e.getAttribute("style") ?? "";
|
|
393
459
|
e.hasAttribute("bgcolor") && (c += `;background-color:${e.getAttribute("bgcolor")}`);
|
|
394
|
-
let l =
|
|
460
|
+
let l = re(c, r);
|
|
395
461
|
if (l && s.setAttribute("style", l), o === "td" || o === "th") for (let t of ["colspan", "rowspan"]) {
|
|
396
462
|
let n = e.getAttribute(t);
|
|
397
463
|
n && /^\d+$/.test(n) && Number(n) >= 1 && Number(n) <= 100 && s.setAttribute(t, String(Number(n)));
|
|
@@ -400,36 +466,36 @@ function M(e) {
|
|
|
400
466
|
t.appendChild(s);
|
|
401
467
|
}
|
|
402
468
|
for (let e of t.childNodes) a(e, n, 0);
|
|
403
|
-
|
|
469
|
+
ae(n);
|
|
404
470
|
let o = /* @__PURE__ */ new Set(), s = document.createTreeWalker(n, NodeFilter.SHOW_TEXT);
|
|
405
471
|
for (; s.nextNode();) for (let e of s.currentNode.textContent.matchAll(/\{([^{}]+)\}/g)) {
|
|
406
472
|
let t = e[1];
|
|
407
|
-
/^[A-Za-z0-9_.]+$/.test(t) && o.add(t),
|
|
473
|
+
/^[A-Za-z0-9_.]+$/.test(t) && o.add(t), P(t) || M(r, "invalid-variable", `Проверьте переменную {${t}}: используйте ASCII-путь без пустых сегментов, до 100 символов.`);
|
|
408
474
|
}
|
|
409
475
|
let c = n.innerHTML || "<p></p>";
|
|
410
|
-
if (new TextEncoder().encode(c).length > 1048576) throw new
|
|
476
|
+
if (new TextEncoder().encode(c).length > 1048576) throw new A("HTML превышает 1 МБ (1048576 байт).");
|
|
411
477
|
return {
|
|
412
478
|
html: c,
|
|
413
479
|
variables: [...o],
|
|
414
480
|
warnings: r
|
|
415
481
|
};
|
|
416
482
|
}
|
|
417
|
-
function
|
|
418
|
-
if (!
|
|
483
|
+
function L(e) {
|
|
484
|
+
if (!O.includes(e)) throw new A(`Неподдерживаемая локаль: ${e}.`);
|
|
419
485
|
}
|
|
420
|
-
function
|
|
421
|
-
|
|
486
|
+
function se(e, t) {
|
|
487
|
+
L(t);
|
|
422
488
|
let n = e[t];
|
|
423
|
-
if (!n || !Array.isArray(n.blocks) || !n.blocks.length) throw new
|
|
489
|
+
if (!n || !Array.isArray(n.blocks) || !n.blocks.length) throw new A(`Нет HTML-шаблона для локали ${t}.`);
|
|
424
490
|
return n.blocks.map((e) => {
|
|
425
|
-
if (e.type !== "html" || typeof e.props?.html != "string" || e.style && Object.keys(e.style).length) throw new
|
|
491
|
+
if (e.type !== "html" || typeof e.props?.html != "string" || e.style && Object.keys(e.style).length) throw new A(`Блок ${e.type} или его внешние стили не поддерживаются редактором HTML; содержимое не изменено.`);
|
|
426
492
|
return e.props.html;
|
|
427
493
|
}).join("");
|
|
428
494
|
}
|
|
429
|
-
function
|
|
430
|
-
|
|
431
|
-
for (let t of Object.keys(e))
|
|
432
|
-
let r =
|
|
495
|
+
function ce(e, t, n) {
|
|
496
|
+
L(t);
|
|
497
|
+
for (let t of Object.keys(e)) L(t);
|
|
498
|
+
let r = oe(n);
|
|
433
499
|
return {
|
|
434
500
|
...r,
|
|
435
501
|
locales: {
|
|
@@ -443,25 +509,25 @@ function ie(e, t, n) {
|
|
|
443
509
|
}
|
|
444
510
|
//#endregion
|
|
445
511
|
//#region src/library/hujjat/xml.ts
|
|
446
|
-
var
|
|
512
|
+
var R = "http://schemas.openxmlformats.org/wordprocessingml/2006/main", z = (e) => e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"), B = (e, t) => Array.from(e?.children ?? []).filter((e) => e.namespaceURI === "http://schemas.openxmlformats.org/wordprocessingml/2006/main" && (!t || e.localName === t)), V = (e, t) => B(e, t)[0] ?? null, H = (e, t = "val") => e?.getAttributeNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", t) ?? "", U = (e, t) => H(V(e, t)), W = (e) => e !== null && ![
|
|
447
513
|
"0",
|
|
448
514
|
"false",
|
|
449
515
|
"off",
|
|
450
516
|
"none"
|
|
451
|
-
].includes(
|
|
452
|
-
function
|
|
453
|
-
if (/<!DOCTYPE|<!ENTITY/i.test(e)) throw new
|
|
517
|
+
].includes(H(e)), G = (e) => `${Number(e) / 20}pt`, le = (e) => Object.keys(e).length ? ` style="${z(Object.entries(e).map(([e, t]) => `${e}:${t}`).join(";"))}"` : "";
|
|
518
|
+
function ue(e) {
|
|
519
|
+
if (/<!DOCTYPE|<!ENTITY/i.test(e)) throw new A("XML с DTD/ENTITY не поддерживается.");
|
|
454
520
|
let t = new DOMParser().parseFromString(e, "application/xml");
|
|
455
|
-
if (t.querySelector("parsererror")) throw new
|
|
456
|
-
if (t.getElementsByTagName("*").length > 5e4) throw new
|
|
521
|
+
if (t.querySelector("parsererror")) throw new A("Повреждённый XML в DOCX.");
|
|
522
|
+
if (t.getElementsByTagName("*").length > 5e4) throw new A("Слишком сложный XML в DOCX.");
|
|
457
523
|
return t;
|
|
458
524
|
}
|
|
459
|
-
async function
|
|
525
|
+
async function K(e, t) {
|
|
460
526
|
let n = e.file(t);
|
|
461
|
-
return n ?
|
|
527
|
+
return n ? ue(await new Promise((e, t) => {
|
|
462
528
|
let r = n.internalStream("uint8array"), i = 0, a = [];
|
|
463
529
|
r.on("data", (e) => {
|
|
464
|
-
i += e.length, i > 8388608 ? (r.pause(), t(new
|
|
530
|
+
i += e.length, i > 8388608 ? (r.pause(), t(new A("XML-часть DOCX превышает 8 МиБ."))) : a.push(e);
|
|
465
531
|
}), r.on("error", t), r.on("end", () => {
|
|
466
532
|
let t = new Uint8Array(i), n = 0;
|
|
467
533
|
for (let e of a) t.set(e, n), n += e.length;
|
|
@@ -469,11 +535,11 @@ async function H(e, t) {
|
|
|
469
535
|
}), r.resume();
|
|
470
536
|
})) : null;
|
|
471
537
|
}
|
|
472
|
-
function
|
|
538
|
+
function q(e) {
|
|
473
539
|
let t = {};
|
|
474
|
-
|
|
475
|
-
let n =
|
|
476
|
-
r && (t["font-family"] = r),
|
|
540
|
+
V(e, "vanish") && (t["--az-hidden"] = W(V(e, "vanish")) ? "1" : "0");
|
|
541
|
+
let n = V(e, "rFonts"), r = H(n, "ascii") || H(n, "hAnsi") || H(n, "cs");
|
|
542
|
+
r && (t["font-family"] = r), U(e, "sz") && (t["font-size"] = `${Number(U(e, "sz")) / 2}pt`);
|
|
477
543
|
for (let [n, r, i, a] of [[
|
|
478
544
|
"b",
|
|
479
545
|
"font-weight",
|
|
@@ -484,119 +550,211 @@ function U(e) {
|
|
|
484
550
|
"font-style",
|
|
485
551
|
"italic",
|
|
486
552
|
"normal"
|
|
487
|
-
]])
|
|
553
|
+
]]) V(e, n) && (t[r] = W(V(e, n)) ? i : a);
|
|
488
554
|
let i = [];
|
|
489
|
-
|
|
490
|
-
let a =
|
|
555
|
+
V(e, "u") && (W(V(e, "u")) ? i.push("underline") : t["text-decoration"] = "none"), (W(V(e, "strike")) || W(V(e, "dstrike"))) && i.push("line-through"), i.length && (t["text-decoration"] = i.join(" "));
|
|
556
|
+
let a = U(e, "color");
|
|
491
557
|
/^[\da-f]{6}$/i.test(a) && (t.color = `#${a}`);
|
|
492
|
-
let o =
|
|
493
|
-
return /^[\da-f]{6}$/i.test(o) ? t["background-color"] = `#${o}` :
|
|
558
|
+
let o = H(V(e, "shd"), "fill");
|
|
559
|
+
return /^[\da-f]{6}$/i.test(o) ? t["background-color"] = `#${o}` : U(e, "highlight") && U(e, "highlight") !== "none" && (t["background-color"] = U(e, "highlight")), ["superscript", "subscript"].includes(U(e, "vertAlign")) && (t["vertical-align"] = U(e, "vertAlign") === "superscript" ? "super" : "sub"), W(V(e, "caps")) && (t["text-transform"] = "uppercase"), U(e, "spacing") && (t["letter-spacing"] = G(U(e, "spacing"))), U(e, "position") && (t["--az-position"] = U(e, "position")), t;
|
|
494
560
|
}
|
|
495
|
-
function
|
|
496
|
-
let t = {}, n =
|
|
561
|
+
function de(e) {
|
|
562
|
+
let t = {}, n = U(e, "jc");
|
|
497
563
|
n && (t["text-align"] = {
|
|
498
564
|
both: "justify",
|
|
499
565
|
distribute: "justify",
|
|
500
566
|
start: "left",
|
|
501
567
|
end: "right"
|
|
502
568
|
}[n] ?? n);
|
|
503
|
-
let r =
|
|
504
|
-
for (let [e, n] of [["before", "margin-top"], ["after", "margin-bottom"]])
|
|
505
|
-
|
|
506
|
-
let i =
|
|
569
|
+
let r = V(e, "spacing");
|
|
570
|
+
for (let [e, n] of [["before", "margin-top"], ["after", "margin-bottom"]]) H(r, e) && (t[n] = G(H(r, e)));
|
|
571
|
+
H(r, "line") && (t["line-height"] = H(r, "lineRule") === "auto" || !H(r, "lineRule") ? String(Number(H(r, "line")) / 240) : G(H(r, "line")));
|
|
572
|
+
let i = V(e, "ind");
|
|
507
573
|
for (let [e, n] of [
|
|
508
574
|
["left", "margin-left"],
|
|
509
575
|
["right", "margin-right"],
|
|
510
576
|
["firstLine", "text-indent"]
|
|
511
|
-
])
|
|
512
|
-
|
|
577
|
+
]) H(i, e) && (t[n] = G(H(i, e)));
|
|
578
|
+
H(i, "hanging") && (t["text-indent"] = G(-Number(H(i, "hanging"))));
|
|
579
|
+
for (let [n, r, i] of [
|
|
580
|
+
[
|
|
581
|
+
"pageBreakBefore",
|
|
582
|
+
"page-break-before",
|
|
583
|
+
"always"
|
|
584
|
+
],
|
|
585
|
+
[
|
|
586
|
+
"keepNext",
|
|
587
|
+
"page-break-after",
|
|
588
|
+
"avoid"
|
|
589
|
+
],
|
|
590
|
+
[
|
|
591
|
+
"keepLines",
|
|
592
|
+
"page-break-inside",
|
|
593
|
+
"avoid"
|
|
594
|
+
]
|
|
595
|
+
]) {
|
|
596
|
+
let a = V(e, n);
|
|
597
|
+
a && (t[r] = W(a) ? i : "auto");
|
|
598
|
+
}
|
|
599
|
+
return t;
|
|
513
600
|
}
|
|
514
|
-
function
|
|
601
|
+
function fe(e) {
|
|
515
602
|
if (!e) return;
|
|
516
|
-
if (["nil", "none"].includes(
|
|
603
|
+
if (["nil", "none"].includes(H(e))) return "none";
|
|
517
604
|
let t = {
|
|
518
605
|
double: "double",
|
|
519
606
|
dotted: "dotted",
|
|
520
607
|
dashed: "dashed"
|
|
521
|
-
}[
|
|
522
|
-
return `${Number(
|
|
608
|
+
}[H(e)] ?? "solid", n = H(e, "color");
|
|
609
|
+
return `${Number(H(e, "sz") || 4) / 8}pt ${t} ${/^[\da-f]{6}$/i.test(n) ? "#" + n : "#000000"}`;
|
|
610
|
+
}
|
|
611
|
+
//#endregion
|
|
612
|
+
//#region src/library/hujjat/page-layout.ts
|
|
613
|
+
function pe(e) {
|
|
614
|
+
let t = E().page, n = V(e, "pgSz"), r = V(e, "pgMar"), i = (e, t, n) => H(e, t) === "" ? n : Number(H(e, t)), a = i(n, "w", t.widthTwips), o = i(n, "h", t.heightTwips);
|
|
615
|
+
return E({ page: {
|
|
616
|
+
widthTwips: a,
|
|
617
|
+
heightTwips: o,
|
|
618
|
+
orientation: H(n, "orient") || (a > o ? "landscape" : "portrait"),
|
|
619
|
+
margins: Object.fromEntries(Object.entries(t.margins).map(([e, t]) => [e, i(r, e, t)]))
|
|
620
|
+
} }).page;
|
|
621
|
+
}
|
|
622
|
+
function me(e, t, n) {
|
|
623
|
+
let r = E(t), i = Array.from(e.getElementsByTagNameNS(R, "sectPr")), a;
|
|
624
|
+
try {
|
|
625
|
+
a = i.map(pe);
|
|
626
|
+
} catch (e) {
|
|
627
|
+
M(n, "unsupported-page-layout", e instanceof Error ? e.message : "Неподдерживаемые параметры страницы.", "loss", {
|
|
628
|
+
stage: "export",
|
|
629
|
+
location: { part: "word/document.xml" }
|
|
630
|
+
});
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (i.length > 1 && M(n, "section-normalized", "HTML не хранит границы и типы переходов разделов Word.", "loss", {
|
|
634
|
+
stage: "export",
|
|
635
|
+
location: { part: "word/document.xml" },
|
|
636
|
+
before: i.length,
|
|
637
|
+
after: 1
|
|
638
|
+
}), a.some((e) => !D(e, a[0]))) return;
|
|
639
|
+
let o = a[0] ?? E().page;
|
|
640
|
+
return D(o, E().page) || M(n, "layout-not-carried-by-html", "Размеры и поля страницы переданы отдельно в layout. Старый HTML/PDF-контракт их не применяет.", "warning", {
|
|
641
|
+
stage: "export",
|
|
642
|
+
location: {
|
|
643
|
+
part: "word/document.xml",
|
|
644
|
+
sectionIndex: 0
|
|
645
|
+
}
|
|
646
|
+
}), {
|
|
647
|
+
...r,
|
|
648
|
+
page: o
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
//#endregion
|
|
652
|
+
//#region src/library/hujjat/paragraph-format.ts
|
|
653
|
+
function he(e) {
|
|
654
|
+
let t, n = "auto";
|
|
655
|
+
for (let r of e) {
|
|
656
|
+
let e = V(r, "spacing");
|
|
657
|
+
H(e, "line") !== "" && (t = Number(H(e, "line")));
|
|
658
|
+
let i = H(e, "lineRule");
|
|
659
|
+
(i === "auto" || i === "exact" || i === "atLeast") && (n = i);
|
|
660
|
+
}
|
|
661
|
+
return t !== void 0 && Number.isFinite(t) ? {
|
|
662
|
+
value: t,
|
|
663
|
+
rule: n
|
|
664
|
+
} : void 0;
|
|
665
|
+
}
|
|
666
|
+
function ge(e) {
|
|
667
|
+
return e.rule === "auto" ? String(e.value / 240) : `${e.value / 20}pt`;
|
|
668
|
+
}
|
|
669
|
+
function _e(e) {
|
|
670
|
+
return (parseFloat(e["font-size"]) || 12) + Math.abs(Number(e["--az-position"]) || 0) / 2;
|
|
523
671
|
}
|
|
524
672
|
//#endregion
|
|
525
673
|
//#region src/library/hujjat/docx-to-html.ts
|
|
526
|
-
async function
|
|
527
|
-
if (e.byteLength > 31457280) throw new
|
|
528
|
-
let
|
|
674
|
+
async function ve(e, t = {}) {
|
|
675
|
+
if (e.byteLength > 31457280) throw new A("DOCX превышает 30 МиБ.");
|
|
676
|
+
let n;
|
|
529
677
|
try {
|
|
530
|
-
|
|
678
|
+
n = await p.loadAsync(e);
|
|
531
679
|
} catch {
|
|
532
|
-
throw new
|
|
680
|
+
throw new A("Повреждённый файл DOCX.");
|
|
533
681
|
}
|
|
534
|
-
let
|
|
535
|
-
if (
|
|
536
|
-
if (
|
|
537
|
-
let
|
|
538
|
-
if (!Array.from(
|
|
539
|
-
let
|
|
540
|
-
if (!
|
|
541
|
-
let
|
|
542
|
-
|
|
543
|
-
|
|
682
|
+
let r = Object.keys(n.files);
|
|
683
|
+
if (r.length > 2e3) throw new A("В DOCX более 2000 частей.");
|
|
684
|
+
if (r.some((e) => /vbaProject\.bin$/i.test(e))) throw new A("DOCX с макросами не поддерживается.");
|
|
685
|
+
let i = await K(n, "[Content_Types].xml");
|
|
686
|
+
if (!Array.from(i?.getElementsByTagNameNS("*", "Override") ?? []).some((e) => e.getAttribute("PartName") === "/word/document.xml" && e.getAttribute("ContentType") === "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml")) throw new A("Файл не является обычным DOCX.");
|
|
687
|
+
let a = await K(n, "word/document.xml"), o = await K(n, "word/styles.xml"), s = await K(n, "word/numbering.xml"), c = V(a?.documentElement, "body");
|
|
688
|
+
if (!c) throw new A("В DOCX нет поддерживаемой структуры документа.");
|
|
689
|
+
let l = [], u = me(c, t, l), d, f = (e, t, n = "warning", r, i) => M(l, e, t, n, {
|
|
690
|
+
stage: "export",
|
|
691
|
+
location: d ? { ...d } : void 0,
|
|
692
|
+
before: r,
|
|
693
|
+
after: i
|
|
694
|
+
}), m = (e, t) => f(e, t, "loss"), h = new Map(Array.from(c.getElementsByTagNameNS(R, "p")).map((e, t) => [e, t])), g = 0;
|
|
695
|
+
r.some((e) => /^word\/(header|footer)[^/]*\.xml$/.test(e)) && m("header-footer-removed", "Колонтитулы Word не входят в HTML-блок; футер формирует Hujjat."), r.some((e) => /^word\/comments/.test(e)) && m("review-removed", "Комментарии Word не сохраняются в HTML.");
|
|
696
|
+
let _ = V(o?.documentElement, "docDefaults"), v = {
|
|
544
697
|
"margin-top": "0pt",
|
|
545
698
|
"margin-bottom": "8px",
|
|
546
|
-
...
|
|
547
|
-
},
|
|
699
|
+
...de(V(V(_, "pPrDefault"), "pPr"))
|
|
700
|
+
}, y = {
|
|
548
701
|
"font-family": "freeserif",
|
|
549
702
|
"font-size": "12pt",
|
|
550
703
|
color: "#111111",
|
|
551
|
-
...
|
|
552
|
-
},
|
|
553
|
-
function
|
|
704
|
+
...q(V(V(_, "rPrDefault"), "rPr"))
|
|
705
|
+
}, b = new Map(B(o?.documentElement, "style").map((e) => [H(e, "styleId"), e]));
|
|
706
|
+
function x(e, t = /* @__PURE__ */ new Set()) {
|
|
554
707
|
if (!e || t.has(e) || t.size > 30) return [];
|
|
555
708
|
t.add(e);
|
|
556
|
-
let n =
|
|
557
|
-
return n ? [...
|
|
709
|
+
let n = b.get(e);
|
|
710
|
+
return n ? [...x(U(n, "basedOn"), t), n] : [];
|
|
558
711
|
}
|
|
559
|
-
let
|
|
560
|
-
if (++
|
|
712
|
+
let S = B(o?.documentElement, "style").find((e) => H(e, "type") === "paragraph" && H(e, "default") === "1"), C = new Map(B(s?.documentElement, "num").map((e) => [H(e, "numId"), e])), w = new Map(B(s?.documentElement, "abstractNum").map((e) => [H(e, "abstractNumId"), e])), T = /* @__PURE__ */ new Set(), E = !1, D = 0, O = (e) => {
|
|
713
|
+
if (++D > 5e4 || e > 80) throw new A("DOCX слишком сложный для HTML-адаптера.");
|
|
561
714
|
};
|
|
562
|
-
function
|
|
563
|
-
if (
|
|
715
|
+
function k(e, t, n) {
|
|
716
|
+
if (O(n), e.namespaceURI !== "http://schemas.openxmlformats.org/wordprocessingml/2006/main") return m("unsupported-content", "Нестандартный объект Word не сохраняется в HTML."), "";
|
|
564
717
|
switch (e.localName) {
|
|
565
|
-
case "t": return
|
|
566
|
-
let t = e === " " &&
|
|
567
|
-
return
|
|
718
|
+
case "t": return z(Array.from(e.textContent ?? "").map((e) => {
|
|
719
|
+
let t = e === " " && E ? "\xA0" : e;
|
|
720
|
+
return E = e === " ", t;
|
|
568
721
|
}).join(""));
|
|
569
|
-
case "tab": return
|
|
570
|
-
case "br": return
|
|
722
|
+
case "tab": return m("tab-normalized", "Положение текста после табуляции потеряно в HTML. Для точного расположения используйте исходный DOCX."), " ";
|
|
723
|
+
case "br": return H(e, "type") === "page" ? "<div style=\"page-break-before:always\"></div>" : "<br>";
|
|
571
724
|
case "cr": return "<br>";
|
|
572
725
|
case "noBreakHyphen": return "‑";
|
|
573
726
|
case "softHyphen": return "";
|
|
574
727
|
case "r": {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
728
|
+
d = {
|
|
729
|
+
...d,
|
|
730
|
+
runIndex: g++
|
|
731
|
+
};
|
|
732
|
+
let r = V(e, "rPr"), i = Object.assign({}, t, ...x(U(r, "rStyle")).map((e) => q(V(e, "rPr"))), q(r));
|
|
733
|
+
if (i["--az-hidden"] === "1") return m("hidden-text-removed", "Скрытый текст Word исключён из HTML."), "";
|
|
734
|
+
Number(i["--az-position"]) && f("baseline-shift-lost", "Вертикальное смещение фрагмента Word не представлено в HTML.", "loss", Number(i["--az-position"]) / 2, 0);
|
|
735
|
+
let a = Object.fromEntries(Object.entries(i).filter(([e]) => !e.startsWith("--az-")));
|
|
736
|
+
return B(e).filter((e) => e.localName !== "rPr").map((e) => k(e, i, n + 1)).join("").split(/(<div style="page-break-before:always"><\/div>)/).map((e) => e.startsWith("<div ") ? e : e ? `<span${le(a)}>${e}</span>` : "").join("");
|
|
579
737
|
}
|
|
580
738
|
case "hyperlink":
|
|
581
|
-
|
|
739
|
+
M(l, "hyperlink-removed", "Ссылки сохраняются как текст без перехода.");
|
|
582
740
|
break;
|
|
583
741
|
case "del":
|
|
584
|
-
case "moveFrom": return
|
|
742
|
+
case "moveFrom": return m("review-removed", "Исправления Word преобразуются в итоговый текст; история теряется."), "";
|
|
585
743
|
case "ins":
|
|
586
744
|
case "moveTo":
|
|
587
|
-
|
|
745
|
+
m("review-removed", "Исправления Word преобразуются в итоговый текст; история теряется.");
|
|
588
746
|
break;
|
|
589
747
|
case "drawing":
|
|
590
748
|
case "pict":
|
|
591
|
-
case "object": return
|
|
749
|
+
case "object": return m("drawing-removed", "Изображения, фигуры и текстовые блоки Word не поддерживаются HTML-блоком Hujjat."), "";
|
|
592
750
|
case "footnoteReference":
|
|
593
|
-
case "endnoteReference": return
|
|
751
|
+
case "endnoteReference": return m("notes-removed", "Сноски Word не поддерживаются HTML-блоком."), "";
|
|
594
752
|
case "instrText":
|
|
595
|
-
case "fldChar": return
|
|
753
|
+
case "fldChar": return m("field-flattened", "Поля Word сохраняют только имеющийся текстовый результат."), "";
|
|
596
754
|
case "fldSimple":
|
|
597
|
-
|
|
755
|
+
m("field-flattened", "Поля Word сохраняют только имеющийся текстовый результат.");
|
|
598
756
|
break;
|
|
599
|
-
case "sdt": return
|
|
757
|
+
case "sdt": return m("content-control-flattened", "Элементы управления Word преобразуются в обычный текст."), V(e, "sdtContent") ? k(V(e, "sdtContent"), t, n + 1) : "";
|
|
600
758
|
case "sdtContent":
|
|
601
759
|
case "smartTag":
|
|
602
760
|
case "customXml": break;
|
|
@@ -607,104 +765,123 @@ async function le(e) {
|
|
|
607
765
|
case "commentRangeStart":
|
|
608
766
|
case "commentRangeEnd":
|
|
609
767
|
case "commentReference": return "";
|
|
610
|
-
default:
|
|
768
|
+
default: m("unsupported-inline", `Элемент Word ${e.localName} не поддерживается HTML-адаптером.`);
|
|
611
769
|
}
|
|
612
|
-
return Array.from(e.children).map((e) =>
|
|
770
|
+
return Array.from(e.children).map((e) => k(e, t, n + 1)).join("");
|
|
613
771
|
}
|
|
614
|
-
function
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
let
|
|
622
|
-
|
|
623
|
-
|
|
772
|
+
function j(e, n) {
|
|
773
|
+
d = {
|
|
774
|
+
part: "word/document.xml",
|
|
775
|
+
paragraphIndex: h.get(e)
|
|
776
|
+
}, g = 0;
|
|
777
|
+
let r = V(e, "pPr"), i = x(U(r, "pStyle") || H(S, "styleId")), a = [...i.map((e) => V(e, "pPr")), r], o = Object.assign({}, v, ...a.map(de)), s = a.map((e) => V(e, "numPr")).filter(Boolean).at(-1), c = U(s, "numId"), u = Number(U(s, "ilvl") || 0), p = U(r, "pStyle") === "AzHujjatListContinuation";
|
|
778
|
+
if (c && c !== "0" || p) {
|
|
779
|
+
let e = C.get(c), t = de(V(B(w.get(U(e, "abstractNumId")), "lvl").find((e) => H(e, "ilvl") === String(u)), "pPr"));
|
|
780
|
+
o["margin-left"] = G((parseFloat(o["margin-left"] ?? t["margin-left"] ?? "0") || 0) * 20 - 360), o["text-indent"] ??= t["text-indent"] ?? "0pt";
|
|
781
|
+
}
|
|
782
|
+
let b = he([V(V(_, "pPrDefault"), "pPr"), ...a]);
|
|
783
|
+
b && (o["line-height"] = ge(b));
|
|
784
|
+
let T = Object.assign({}, y, ...i.map((e) => q(V(e, "rPr")))), D = Array.from(e.getElementsByTagNameNS(R, "r")).map((e) => {
|
|
785
|
+
let t = V(e, "rPr"), n = Object.assign({}, T, ...x(U(t, "rStyle")).map((e) => q(V(e, "rPr"))), q(t));
|
|
786
|
+
return n["--az-hidden"] === "1" ? 0 : _e(n);
|
|
787
|
+
}), O = o["line-height"];
|
|
788
|
+
O && (/^\d*\.?\d+$/.test(O) ? Number(O) < 1 : O.endsWith("pt") && parseFloat(O) < Math.max(_e(T), ...D)) && (t.lineSpacingPolicy === "preserve" ? f("line-height-overlap-risk", "Авторский тесный интервал сохранён; строки могут перекрываться. Фактические метрики шрифта требуют проверки.", "warning", O, O) : (o["line-height"] = /^\d*\.?\d+$/.test(O) ? "1" : "normal", f("line-height-normalized", "Тесный межстрочный интервал нормализован по размерам фрагментов. Проверьте переносы на используемых шрифтах.", "warning", O, o["line-height"]))), b && b.rule !== "auto" && f("line-rule-lost", "CSS line-height не сохраняет различие правил Word exact и atLeast.", "warning", b.rule, "CSS line-height"), a.some((e) => V(e, "tabs")) && m("tab-stops-removed", "Позиции, типы и заполнители табуляции не поддерживаются HTML-блоком.");
|
|
789
|
+
let A = [V(V(_, "pPrDefault"), "pPr"), ...a].map((e) => V(e, "widowControl")).filter(Boolean).at(-1);
|
|
790
|
+
A && M(l, "widow-control-lost", "Правило висячих строк Word не представлено в HTML-контракте.", "loss", {
|
|
791
|
+
stage: "export",
|
|
792
|
+
location: { ...d },
|
|
793
|
+
before: W(A),
|
|
794
|
+
after: null
|
|
795
|
+
}), E = !0;
|
|
796
|
+
let j = Array.from(e.children).filter((e) => e !== r).map((e) => k(e, T, n + 1)).join("").split("<div style=\"page-break-before:always\"></div>").map((e, t) => `${t ? "<div style=\"page-break-before:always\"></div>" : ""}<p${le(o)}>${e || "<br>"}</p>`).join("");
|
|
797
|
+
if (c && c !== "0") {
|
|
798
|
+
let e = C.get(c), t = B(w.get(U(e, "abstractNumId")), "lvl").find((e) => H(e, "ilvl") === String(u));
|
|
799
|
+
if (!t) return M(l, "numbering-unsupported", "Не найдена нумерация списка.", "loss"), { html: j };
|
|
800
|
+
let n = U(t, "numFmt");
|
|
801
|
+
return (!["decimal", "bullet"].includes(n) || u || U(t, "start") && U(t, "start") !== "1" || V(e, "lvlOverride")) && M(l, "numbering-normalized", "Сложная нумерация/начальное число списка заменены обычным HTML-списком.", "loss"), {
|
|
802
|
+
html: j,
|
|
624
803
|
list: {
|
|
625
|
-
id:
|
|
626
|
-
level: Math.min(
|
|
804
|
+
id: c,
|
|
805
|
+
level: Math.min(u, 8),
|
|
627
806
|
tag: n === "bullet" ? "ul" : "ol"
|
|
628
807
|
}
|
|
629
808
|
};
|
|
630
809
|
}
|
|
631
810
|
return {
|
|
632
|
-
html:
|
|
633
|
-
continuation:
|
|
811
|
+
html: j,
|
|
812
|
+
continuation: U(r, "pStyle") === "AzHujjatListContinuation"
|
|
634
813
|
};
|
|
635
814
|
}
|
|
636
|
-
function
|
|
637
|
-
|
|
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 =
|
|
649
|
-
if (e.rowSpan++, e.rowSpan > 100) throw new
|
|
650
|
-
|
|
815
|
+
function N(e, t) {
|
|
816
|
+
O(t);
|
|
817
|
+
let n = V(e, "tblPr");
|
|
818
|
+
U(n, "tblStyle") && M(l, "table-style-normalized", "Условные стили таблиц Word могут отличаться; проверьте границы и заливку.");
|
|
819
|
+
let r = V(n, "tblBorders"), i = B(V(e, "tblGrid"), "gridCol").map((e) => Number(H(e, "w"))), a = H(V(n, "tblLayout"), "type") === "fixed", o = B(e, "tr"), s = /* @__PURE__ */ new Map(), c = Math.max(1, ...o.map((e) => B(e, "tc").reduce((e, t) => e + Number(U(V(t, "tcPr"), "gridSpan") || 1), 0))), u = [];
|
|
820
|
+
o.forEach((e, l) => {
|
|
821
|
+
let d = 0, f = [];
|
|
822
|
+
Number(U(V(e, "trPr"), "gridBefore") || 0) && m("table-grid-unsupported", "Таблица с пропущенными начальными ячейками требует проверки.");
|
|
823
|
+
for (let u of B(e, "tc")) {
|
|
824
|
+
let e = V(u, "tcPr"), p = Number(U(e, "gridSpan") || 1), h = V(e, "vMerge");
|
|
825
|
+
if (V(e, "hMerge") && m("legacy-table-merge", "Старый формат горизонтального объединения hMerge требует преобразования в gridSpan."), !Number.isInteger(p) || p < 1 || p > 100) throw new A("Объединение таблицы превышает предел 100 ячеек.");
|
|
826
|
+
if (h && H(h) !== "restart" && s.has(d) && s.get(d).span === p) {
|
|
827
|
+
let e = s.get(d);
|
|
828
|
+
if (e.rowSpan++, e.rowSpan > 100) throw new A("Объединение таблицы превышает 100 строк.");
|
|
829
|
+
u.getElementsByTagNameNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "t").length && u.textContent?.trim() && m("table-merge-content", "Текст в продолжении объединённой ячейки требует ручной проверки."), d += p;
|
|
651
830
|
continue;
|
|
652
831
|
}
|
|
653
|
-
let
|
|
654
|
-
|
|
655
|
-
let
|
|
656
|
-
|
|
832
|
+
let g = {}, _ = V(e, "tcW");
|
|
833
|
+
H(_, "type") === "dxa" ? g.width = G(H(_, "w")) : H(_, "type") === "pct" && (g.width = `${Number(H(_, "w")) / 50}%`);
|
|
834
|
+
let v = i.slice(d, d + p);
|
|
835
|
+
(a || !g.width) && v.length === p && v.every((e) => Number.isFinite(e) && e > 0) && (g.width = G(v.reduce((e, t) => e + t, 0)));
|
|
836
|
+
let y = H(V(e, "shd"), "fill");
|
|
837
|
+
/^[\da-f]{6}$/i.test(y) && (g["background-color"] = "#" + y), U(e, "vAlign") && (g["vertical-align"] = U(e, "vAlign") === "center" ? "middle" : U(e, "vAlign"));
|
|
657
838
|
for (let t of [
|
|
658
839
|
"top",
|
|
659
840
|
"right",
|
|
660
841
|
"bottom",
|
|
661
842
|
"left"
|
|
662
843
|
]) {
|
|
663
|
-
let
|
|
664
|
-
|
|
665
|
-
let
|
|
666
|
-
|
|
844
|
+
let i = V(V(e, "tcBorders"), t), a = t === "top" && l > 0 || t === "bottom" && l < o.length - 1 ? "insideH" : t === "left" && d > 0 || t === "right" && d + p < c ? "insideV" : t, s = V(r, a), u = fe(i ?? s);
|
|
845
|
+
u && (g[`border-${t}`] = u);
|
|
846
|
+
let f = V(V(e, "tcMar"), t) ?? V(V(n, "tblCellMar"), t);
|
|
847
|
+
f && H(f, "w") && (g[`padding-${t}`] = G(H(f, "w")));
|
|
667
848
|
}
|
|
668
|
-
let
|
|
669
|
-
element:
|
|
849
|
+
let b = {
|
|
850
|
+
element: u,
|
|
670
851
|
rowSpan: 1,
|
|
671
|
-
span:
|
|
672
|
-
html:
|
|
673
|
-
css:
|
|
852
|
+
span: p,
|
|
853
|
+
html: P(u, t + 1),
|
|
854
|
+
css: g
|
|
674
855
|
};
|
|
675
|
-
for (let e =
|
|
676
|
-
|
|
856
|
+
for (let e = d; e < d + p; e++) s.delete(e);
|
|
857
|
+
h && H(h) === "restart" && s.set(d, b), f.push(b), d += p;
|
|
677
858
|
}
|
|
678
|
-
for (let e of
|
|
679
|
-
|
|
859
|
+
for (let e of s.keys()) e >= d && s.delete(e);
|
|
860
|
+
u.push(f);
|
|
680
861
|
});
|
|
681
|
-
let
|
|
682
|
-
|
|
683
|
-
width: L(u, "type") === "dxa" ? B(L(u, "w")) : L(u, "type") === "pct" ? `${Number(L(u, "w")) / 50}%` : "100%",
|
|
862
|
+
let d = V(n, "tblW"), f = {
|
|
863
|
+
width: H(d, "type") === "dxa" ? G(H(d, "w")) : H(d, "type") === "pct" ? `${Number(H(d, "w")) / 50}%` : "100%",
|
|
684
864
|
"border-collapse": "collapse"
|
|
685
|
-
}
|
|
865
|
+
}, p = V(n, "tblInd");
|
|
866
|
+
return H(p, "type") === "dxa" && (f["margin-left"] = G(H(p, "w"))), a && (f["table-layout"] = "fixed"), `<table${le(f)}>${u.map((e) => `<tr>${e.map((e) => `<td${e.span > 1 ? ` colspan="${e.span}"` : ""}${e.rowSpan > 1 ? ` rowspan="${e.rowSpan}"` : ""}${le(e.css)}>${e.html || "<p><br></p>"}</td>`).join("")}</tr>`).join("")}</table>`;
|
|
686
867
|
}
|
|
687
|
-
function
|
|
688
|
-
|
|
868
|
+
function P(e, t) {
|
|
869
|
+
O(t);
|
|
689
870
|
let n = "", r, i = () => {
|
|
690
871
|
r && (n += `</${r.tag}>`), r = void 0;
|
|
691
872
|
};
|
|
692
|
-
for (let a of Array.from(e.children)) if (a.namespaceURI !== "http://schemas.openxmlformats.org/wordprocessingml/2006/main") i(),
|
|
873
|
+
for (let a of Array.from(e.children)) if (a.namespaceURI !== "http://schemas.openxmlformats.org/wordprocessingml/2006/main") i(), m("unsupported-content", "Нестандартный блок Word не сохраняется в HTML.");
|
|
693
874
|
else if (a.localName === "p") {
|
|
694
|
-
let e =
|
|
695
|
-
e.list ? ((r?.id !== e.list.id || r.tag !== e.list.tag) && (i(), r = e.list, r.tag === "ol" &&
|
|
696
|
-
} else
|
|
697
|
-
else if (a.localName === "sectPr") {
|
|
698
|
-
let e = I(a, "pgSz"), t = I(a, "pgMar");
|
|
699
|
-
(L(e, "orient") === "landscape" || L(e, "w") && Math.abs(Number(L(e, "w")) - 11906) > 2 || L(t, "bottom") && Math.abs(Number(L(t, "bottom")) - 1984) > 2) && w(c, "page-normalized", "Размеры и поля Word заменяются настройками Hujjat: A4, 15/20/35/20 мм.");
|
|
700
|
-
} else [
|
|
875
|
+
let e = j(a, t + 1);
|
|
876
|
+
e.list ? ((r?.id !== e.list.id || r.tag !== e.list.tag) && (i(), r = e.list, r.tag === "ol" && T.has(r.id) && m("numbering-restart", "Продолжение нумерованного списка после другого блока начнётся с 1: Hujjat удаляет атрибут start."), T.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);
|
|
877
|
+
} else a.localName === "tbl" ? (i(), n += N(a, t + 1)) : a.localName === "sectPr" || ([
|
|
701
878
|
"sdt",
|
|
702
879
|
"customXml",
|
|
703
880
|
"ins",
|
|
704
881
|
"del",
|
|
705
882
|
"moveFrom",
|
|
706
883
|
"moveTo"
|
|
707
|
-
].includes(a.localName) ? (i(),
|
|
884
|
+
].includes(a.localName) ? (i(), m("block-flattened", `Блок Word ${a.localName} преобразован без интерактивности/истории.`), ["del", "moveFrom"].includes(a.localName) || (n += P(V(a, "sdtContent") ?? a, t + 1))) : [
|
|
708
885
|
"tblPr",
|
|
709
886
|
"tblGrid",
|
|
710
887
|
"tcPr",
|
|
@@ -712,17 +889,51 @@ async function le(e) {
|
|
|
712
889
|
"bookmarkStart",
|
|
713
890
|
"bookmarkEnd",
|
|
714
891
|
"proofErr"
|
|
715
|
-
].includes(a.localName) || (i(),
|
|
892
|
+
].includes(a.localName) || (i(), m("unsupported-block", `Блок Word ${a.localName} не поддерживается HTML-адаптером.`)));
|
|
716
893
|
return i(), n;
|
|
717
894
|
}
|
|
718
895
|
return {
|
|
719
|
-
html:
|
|
720
|
-
warnings:
|
|
896
|
+
html: P(c, 0) || "<p><br></p>",
|
|
897
|
+
warnings: l,
|
|
898
|
+
layout: u
|
|
721
899
|
};
|
|
722
900
|
}
|
|
723
901
|
//#endregion
|
|
902
|
+
//#region src/library/hujjat/table-grid.ts
|
|
903
|
+
function ye(e, t, n, r) {
|
|
904
|
+
let i = Array.from({ length: e }), a = () => M(r, "table-width-normalized", "Противоречивые ширины ячеек приведены к общей сетке таблицы.");
|
|
905
|
+
for (let e of [...n].sort((e, t) => e.span - t.span)) {
|
|
906
|
+
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);
|
|
907
|
+
if (!n.length) {
|
|
908
|
+
Math.abs(r - e.width) > 2 && a();
|
|
909
|
+
continue;
|
|
910
|
+
}
|
|
911
|
+
if (e.width <= r) {
|
|
912
|
+
a();
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
let o = (e.width - r) / n.length;
|
|
916
|
+
for (let e of n) i[e] = o;
|
|
917
|
+
}
|
|
918
|
+
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);
|
|
919
|
+
o > t + 2 && a();
|
|
920
|
+
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) => ({
|
|
921
|
+
i: t,
|
|
922
|
+
fraction: e - p[t]
|
|
923
|
+
})).sort((e, t) => t.fraction - e.fraction), h = d - p.reduce((e, t) => e + t, 0);
|
|
924
|
+
for (let e = 0; e < h; e++) p[m[e].i]++;
|
|
925
|
+
if (h < 0) {
|
|
926
|
+
let e = -h;
|
|
927
|
+
for (let { i: t } of [...m].sort((e, t) => p[t.i] - p[e.i])) {
|
|
928
|
+
let n = Math.min(p[t] - 1, e);
|
|
929
|
+
if (p[t] -= n, e -= n, !e) break;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
return p;
|
|
933
|
+
}
|
|
934
|
+
//#endregion
|
|
724
935
|
//#region src/library/hujjat/html-to-docx.ts
|
|
725
|
-
var
|
|
936
|
+
var be = /^(font-|color$|text-align$|text-indent$|text-transform$|line-height$|letter-spacing$|white-space$|text-decoration$|vertical-align$)/, xe = new Set("p div h1 h2 h3 h4 h5 h6 ul ol li table hr".split(" ")), Se = {
|
|
726
937
|
black: "000000",
|
|
727
938
|
white: "FFFFFF",
|
|
728
939
|
red: "FF0000",
|
|
@@ -741,14 +952,14 @@ var ue = /^(font-|color$|text-align$|text-indent$|text-transform$|line-height$|l
|
|
|
741
952
|
teal: "008080",
|
|
742
953
|
aqua: "00FFFF"
|
|
743
954
|
};
|
|
744
|
-
function
|
|
955
|
+
function J(e) {
|
|
745
956
|
if (!e) return;
|
|
746
957
|
if (/^#[\da-f]{6}$/i.test(e)) return e.slice(1);
|
|
747
958
|
if (/^#[\da-f]{3}$/i.test(e)) return e.slice(1).split("").map((e) => e + e).join("");
|
|
748
959
|
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("") :
|
|
960
|
+
return t ? t.slice(1).map((e) => Math.min(255, Number(e)).toString(16).padStart(2, "0")).join("") : Se[e.toLowerCase()];
|
|
750
961
|
}
|
|
751
|
-
function
|
|
962
|
+
function Y(e) {
|
|
752
963
|
if (e === "0") return 0;
|
|
753
964
|
let t = e?.match(/^(-?\d*\.?\d+)(pt|px|in|cm|mm|pc)$/i);
|
|
754
965
|
return t ? Number(t[1]) * {
|
|
@@ -760,11 +971,11 @@ function K(e) {
|
|
|
760
971
|
pc: 12
|
|
761
972
|
}[t[2].toLowerCase()] : void 0;
|
|
762
973
|
}
|
|
763
|
-
var
|
|
764
|
-
let t =
|
|
974
|
+
var X = (e) => {
|
|
975
|
+
let t = Y(e);
|
|
765
976
|
return t === void 0 ? void 0 : Math.round(t * 20);
|
|
766
977
|
};
|
|
767
|
-
function
|
|
978
|
+
function Z(e, t) {
|
|
768
979
|
let n = { ...t }, r = e.style;
|
|
769
980
|
for (let e of Array.from(r)) n[e] = r.getPropertyValue(e).trim();
|
|
770
981
|
for (let e of ["margin", "padding"]) for (let t of [
|
|
@@ -783,76 +994,115 @@ function J(e, t) {
|
|
|
783
994
|
h3: "12pt"
|
|
784
995
|
}[i] ?? "12pt"), r.fontWeight || (n["font-weight"] = "bold")), n;
|
|
785
996
|
}
|
|
786
|
-
var
|
|
787
|
-
async function
|
|
788
|
-
let
|
|
789
|
-
|
|
997
|
+
var Q = (e) => Object.fromEntries(Object.entries(e).filter(([e]) => be.test(e)));
|
|
998
|
+
async function Ce(e, t, n = E()) {
|
|
999
|
+
let r = {
|
|
1000
|
+
width: T(n.page),
|
|
1001
|
+
cell: !1
|
|
1002
|
+
}, i = ie(e), a = 1, o = [], s = /* @__PURE__ */ new WeakMap();
|
|
1003
|
+
function c(e, t) {
|
|
1004
|
+
let n = 0;
|
|
1005
|
+
for (let r of e.childNodes) if (r instanceof Element) {
|
|
1006
|
+
let e = `${t}/${r.localName}[${n++}]`;
|
|
1007
|
+
s.set(r, e), c(r, e);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
c(i, "");
|
|
1011
|
+
let l = [];
|
|
1012
|
+
function u() {
|
|
790
1013
|
let e = !0;
|
|
791
|
-
for (let t of
|
|
1014
|
+
for (let t of l) t.data = t.data.replace(/[\t\r\n\f ]+/g, " ").split("").filter((t) => {
|
|
792
1015
|
if (t === " ") {
|
|
793
1016
|
if (e) return !1;
|
|
794
1017
|
e = !0;
|
|
795
1018
|
} else e = !1;
|
|
796
1019
|
return !0;
|
|
797
1020
|
}).join("");
|
|
798
|
-
for (let e =
|
|
799
|
-
|
|
1021
|
+
for (let e = l.length - 1; e >= 0; e--) if (l[e].data) {
|
|
1022
|
+
l[e].data = l[e].data.replace(/ $/, "");
|
|
800
1023
|
break;
|
|
801
1024
|
}
|
|
802
|
-
|
|
1025
|
+
l = [];
|
|
803
1026
|
}
|
|
804
|
-
function
|
|
1027
|
+
function d(e, n = !1) {
|
|
805
1028
|
if (e.nodeType === 3) {
|
|
806
|
-
n ||
|
|
1029
|
+
n || l.push(e);
|
|
807
1030
|
return;
|
|
808
1031
|
}
|
|
809
|
-
let r = e instanceof Element ? e : null, i = r && (
|
|
1032
|
+
let r = e instanceof Element ? e : null, i = r && (xe.has(r.localName) || [
|
|
810
1033
|
"br",
|
|
811
1034
|
"td",
|
|
812
1035
|
"th",
|
|
813
1036
|
"tr"
|
|
814
|
-
].includes(r.localName)),
|
|
815
|
-
(i ||
|
|
816
|
-
for (let t of e.childNodes)
|
|
817
|
-
(i ||
|
|
1037
|
+
].includes(r.localName)), a = n || !!(r && /^(pre|pre-wrap|break-spaces)$/.test(r.style.whiteSpace));
|
|
1038
|
+
(i || a) && u(), a && M(t, "preformatted-text", "Предформатированный текст требует проверки переносов и табуляции после открытия.");
|
|
1039
|
+
for (let t of e.childNodes) d(t, a);
|
|
1040
|
+
(i || a) && u();
|
|
818
1041
|
}
|
|
819
|
-
|
|
820
|
-
let
|
|
1042
|
+
d(i), u();
|
|
1043
|
+
let f = {
|
|
821
1044
|
"font-family": "freeserif",
|
|
822
1045
|
"font-size": "12pt",
|
|
823
1046
|
color: "#111111"
|
|
824
1047
|
};
|
|
825
|
-
function
|
|
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"}"/>`),
|
|
1048
|
+
function m(e) {
|
|
1049
|
+
let t = `<w:rFonts w:ascii="${z(e["font-family"] || "freeserif")}" w:hAnsi="${z(e["font-family"] || "freeserif")}"/>`, n = Y(e["font-size"]);
|
|
1050
|
+
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"}"/>`), J(e.color) && (t += `<w:color w:val="${J(e.color)}"/>`), J(e["background-color"]) && (t += `<w:shd w:fill="${J(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/>"), X(e["letter-spacing"]) !== void 0 && (t += `<w:spacing w:val="${X(e["letter-spacing"])}"/>`), t;
|
|
828
1051
|
}
|
|
829
|
-
function
|
|
1052
|
+
function h(e, t) {
|
|
830
1053
|
let n = "";
|
|
831
|
-
for (let r of e) r.nodeType === 3 ? r.textContent && (n += `<w:r><w:rPr>${
|
|
1054
|
+
for (let r of e) r.nodeType === 3 ? r.textContent && (n += `<w:r><w:rPr>${m(t)}</w:rPr><w:t xml:space="preserve">${z(r.textContent)}</w:t></w:r>`) : r instanceof Element && (r.localName === "br" ? n += "<w:r><w:br/></w:r>" : n += h(r.childNodes, Z(r, t)));
|
|
832
1055
|
return n;
|
|
833
1056
|
}
|
|
834
|
-
function
|
|
835
|
-
let
|
|
1057
|
+
function g(e, i, a, o = r) {
|
|
1058
|
+
let s = "", c = i["text-align"];
|
|
836
1059
|
[
|
|
837
1060
|
"left",
|
|
838
1061
|
"right",
|
|
839
1062
|
"center",
|
|
840
1063
|
"justify"
|
|
841
|
-
].includes(
|
|
842
|
-
let
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
1064
|
+
].includes(c) && (s += `<w:jc w:val="${c === "justify" ? "both" : c}"/>`);
|
|
1065
|
+
let l = Math.max(o.before ?? 0, X(i["margin-top"]) ?? 0), u = Math.max(o.after ?? 0, X(i["margin-bottom"]) ?? (o.cell ? 0 : 120)), d = "", f = i["line-height"];
|
|
1066
|
+
if (f && /^\d*\.?\d+%?$/.test(f)) {
|
|
1067
|
+
let e = parseFloat(f) / (f.endsWith("%") ? 100 : 1), r = n.lineSpacingPolicy === "preserve";
|
|
1068
|
+
e < 1 && M(t, r ? "line-height-overlap-risk" : "line-height-normalized", r ? "Тесный интервал сохранён; проверьте наложение строк." : "Тесный интервал увеличен до одинарного; проверьте переносы.", "warning", {
|
|
1069
|
+
stage: "import",
|
|
1070
|
+
location: { htmlPath: o.htmlPath },
|
|
1071
|
+
before: e,
|
|
1072
|
+
after: r ? e : 1
|
|
1073
|
+
}), d = ` w:line="${Math.round(Math.max(+!r, e) * 240)}" w:lineRule="auto"`;
|
|
1074
|
+
} else Y(f) !== void 0 && (d = ` w:line="${Math.max(0, X(f))}" w:lineRule="atLeast"`);
|
|
1075
|
+
s += `<w:spacing w:before="${Math.max(0, l)}" w:after="${Math.max(0, u)}"${d}/>`;
|
|
1076
|
+
let p = "";
|
|
1077
|
+
for (let [e, t] of [
|
|
846
1078
|
["margin-left", "left"],
|
|
847
1079
|
["margin-right", "right"],
|
|
848
1080
|
["text-indent", "firstLine"]
|
|
849
1081
|
]) {
|
|
850
|
-
let r =
|
|
851
|
-
|
|
1082
|
+
let n = t === "left" ? o.left : t === "right" ? o.right : void 0, r = X(i[e]), s = a ? t === "left" ? 360 : t === "firstLine" ? a.pending ? -180 : 0 : void 0 : void 0, c = r === void 0 && !n && s === void 0 ? void 0 : (r ?? (t === "firstLine" ? s : 0) ?? 0) + (n ?? 0) + (t === "left" ? s ?? 0 : 0);
|
|
1083
|
+
c !== void 0 && (p += t === "firstLine" && c < 0 ? ` w:hanging="${-c}"` : ` w:${t}="${c}"`);
|
|
852
1084
|
}
|
|
853
|
-
|
|
1085
|
+
p && (s += `<w:ind${p}/>`);
|
|
1086
|
+
for (let [e, t, n] of [
|
|
1087
|
+
[
|
|
1088
|
+
"page-break-before",
|
|
1089
|
+
"pageBreakBefore",
|
|
1090
|
+
"always"
|
|
1091
|
+
],
|
|
1092
|
+
[
|
|
1093
|
+
"page-break-inside",
|
|
1094
|
+
"keepLines",
|
|
1095
|
+
"avoid"
|
|
1096
|
+
],
|
|
1097
|
+
[
|
|
1098
|
+
"page-break-after",
|
|
1099
|
+
"keepNext",
|
|
1100
|
+
"avoid"
|
|
1101
|
+
]
|
|
1102
|
+
]) (i[e] === n || i[e] === "auto") && (s += `<w:${t} w:val="${i[e] === n ? "1" : "0"}"/>`);
|
|
1103
|
+
return a && (a.pending ? s += `<w:numPr><w:ilvl w:val="0"/><w:numId w:val="${a.id}"/></w:numPr>` : s += "<w:pStyle w:val=\"AzHujjatListContinuation\"/>", a.pending = !1), `<w:p><w:pPr>${s}</w:pPr>${h(e, i)}</w:p>` + (i["page-break-after"] === "always" ? "<w:p><w:pPr><w:pageBreakBefore/></w:pPr></w:p>" : "");
|
|
854
1104
|
}
|
|
855
|
-
function
|
|
1105
|
+
function _(e, t) {
|
|
856
1106
|
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;
|
|
857
1107
|
return !r && !i ? "" : `<w:${t} w:val="${{
|
|
858
1108
|
solid: "single",
|
|
@@ -860,335 +1110,607 @@ async function fe(e, t) {
|
|
|
860
1110
|
dotted: "dotted",
|
|
861
1111
|
double: "double",
|
|
862
1112
|
none: "nil"
|
|
863
|
-
}[r] ?? "single"}" w:sz="${Math.max(0, Math.round((
|
|
1113
|
+
}[r] ?? "single"}" w:sz="${Math.max(0, Math.round((Y(i) ?? .75) * 8))}" w:color="${J(a) ?? "000000"}"/>`;
|
|
864
1114
|
}
|
|
865
|
-
function
|
|
866
|
-
let
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1115
|
+
function v(e, n, r) {
|
|
1116
|
+
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 = (r.left ?? 0) + (X(n["margin-left"]) ?? 0), u = (r.right ?? 0) + (X(n["margin-right"]) ?? 0), d = Math.max(1, r.width - l - u), f = Math.max(1, Math.round(X(n.width) ?? (c === void 0 ? d : d * c / 100)));
|
|
1117
|
+
(r.before || r.after || X(n["margin-top"]) || X(n["margin-bottom"])) && M(t, "table-margin-approximation", "Вертикальные отступы контейнера вокруг таблицы требуют проверки.");
|
|
1118
|
+
let p = (e) => {
|
|
1119
|
+
if (e > 1e3) throw new A("Таблица содержит более 1000 столбцов с учётом объединённых ячеек.");
|
|
1120
|
+
}, m = i.map((t) => {
|
|
1121
|
+
let r = 0, i = [];
|
|
870
1122
|
function c() {
|
|
871
|
-
for (;
|
|
872
|
-
let e =
|
|
873
|
-
|
|
1123
|
+
for (; a.has(r);) {
|
|
1124
|
+
let e = a.get(r);
|
|
1125
|
+
i.push({
|
|
1126
|
+
column: r,
|
|
1127
|
+
span: e.span,
|
|
1128
|
+
rowSpan: 0,
|
|
1129
|
+
css: {}
|
|
1130
|
+
}), --e.remaining === 0 && a.delete(r), r += e.span, p(r);
|
|
874
1131
|
}
|
|
875
1132
|
}
|
|
876
|
-
for (let
|
|
1133
|
+
for (let o of Array.from(t.children).filter((e) => e.localName === "td" || e.localName === "th")) {
|
|
877
1134
|
c();
|
|
878
|
-
let
|
|
879
|
-
|
|
880
|
-
let u = [], d =
|
|
1135
|
+
let t = Number(o.getAttribute("colspan") || 1), l = Number(o.getAttribute("rowspan") || 1);
|
|
1136
|
+
p(r + t);
|
|
1137
|
+
let u = [], d = o.parentElement;
|
|
881
1138
|
for (; d && d !== e;) u.unshift(d), d = d.parentElement;
|
|
882
|
-
let
|
|
883
|
-
...
|
|
1139
|
+
let m = (e) => ({
|
|
1140
|
+
...Q(e),
|
|
884
1141
|
...e["background-color"] ? { "background-color": e["background-color"] } : {}
|
|
885
|
-
}),
|
|
886
|
-
|
|
887
|
-
let g =
|
|
888
|
-
|
|
1142
|
+
}), h = Z(o, m(u.reduce((e, t) => Z(t, m(e)), n)));
|
|
1143
|
+
o.localName === "th" && (h["font-weight"] = "bold");
|
|
1144
|
+
let g = X(h.width) ?? (h.width?.endsWith("%") ? parseFloat(h.width) * f / 100 : void 0);
|
|
1145
|
+
g !== void 0 && Number.isFinite(g) && g > 0 && s.push({
|
|
1146
|
+
column: r,
|
|
1147
|
+
span: t,
|
|
1148
|
+
width: g
|
|
1149
|
+
}), i.push({
|
|
1150
|
+
element: o,
|
|
1151
|
+
column: r,
|
|
1152
|
+
span: t,
|
|
1153
|
+
rowSpan: l,
|
|
1154
|
+
css: h
|
|
1155
|
+
}), l > 1 && a.set(r, {
|
|
889
1156
|
remaining: l - 1,
|
|
890
|
-
span:
|
|
891
|
-
})
|
|
892
|
-
let _ = G(m["background-color"]);
|
|
893
|
-
_ && (g += `<w:shd w:fill="${_}"/>`), [
|
|
894
|
-
"top",
|
|
895
|
-
"middle",
|
|
896
|
-
"bottom"
|
|
897
|
-
].includes(m["vertical-align"]) && (g += `<w:vAlign w:val="${m["vertical-align"] === "middle" ? "center" : m["vertical-align"]}"/>`);
|
|
898
|
-
let v = q(m.width);
|
|
899
|
-
v === void 0 ? m.width?.endsWith("%") && (g += `<w:tcW w:w="${Math.round(parseFloat(m.width) * 50)}" w:type="pct"/>`) : g += `<w:tcW w:w="${Math.max(0, v)}" w:type="dxa"/>`;
|
|
900
|
-
let y = [
|
|
901
|
-
"top",
|
|
902
|
-
"left",
|
|
903
|
-
"bottom",
|
|
904
|
-
"right"
|
|
905
|
-
], b = y.map((e) => p(i, e)).join("");
|
|
906
|
-
b && (g += `<w:tcBorders>${b}</w:tcBorders>`);
|
|
907
|
-
let x = y.map((e) => q(m[`padding-${e}`]) === void 0 ? "" : `<w:${e} w:w="${Math.max(0, q(m[`padding-${e}`]))}" w:type="dxa"/>`).join("");
|
|
908
|
-
x && (g += `<w:tcMar>${x}</w:tcMar>`);
|
|
909
|
-
let S = h(i.childNodes, Y(m));
|
|
910
|
-
(!S || S.endsWith("</w:tbl>")) && (S += "<w:p/>"), s += `<w:tc><w:tcPr>${g}</w:tcPr>${S}</w:tc>`, o += n;
|
|
1157
|
+
span: t
|
|
1158
|
+
}), r += t;
|
|
911
1159
|
}
|
|
912
|
-
|
|
913
|
-
|
|
1160
|
+
for (;;) {
|
|
1161
|
+
let e = [...a.keys()].filter((e) => e >= r).sort((e, t) => e - t)[0];
|
|
1162
|
+
if (e === void 0) break;
|
|
1163
|
+
for (; r < e;) i.push({
|
|
1164
|
+
column: r,
|
|
1165
|
+
span: 1,
|
|
1166
|
+
rowSpan: 1,
|
|
1167
|
+
css: {}
|
|
1168
|
+
}), r++;
|
|
1169
|
+
c();
|
|
1170
|
+
}
|
|
1171
|
+
return o = Math.max(o, r), i;
|
|
1172
|
+
}), h = ye(o, f, s, t), g = "<w:p><w:pPr><w:spacing w:before=\"0\" w:after=\"0\"/></w:pPr></w:p>", v = m.map((e) => `<w:tr>${e.map(({ element: e, column: t, span: n, rowSpan: r, css: i }) => {
|
|
1173
|
+
let a = h.slice(t, t + n).reduce((e, t) => e + t, 0), o = `<w:tcW w:w="${a}" w:type="dxa"/>`;
|
|
1174
|
+
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>${g}</w:tc>`;
|
|
1175
|
+
let s = J(i["background-color"]);
|
|
1176
|
+
s && (o += `<w:shd w:fill="${s}"/>`), [
|
|
1177
|
+
"top",
|
|
1178
|
+
"middle",
|
|
1179
|
+
"bottom"
|
|
1180
|
+
].includes(i["vertical-align"]) && (o += `<w:vAlign w:val="${i["vertical-align"] === "middle" ? "center" : i["vertical-align"]}"/>`);
|
|
1181
|
+
let c = [
|
|
1182
|
+
"top",
|
|
1183
|
+
"left",
|
|
1184
|
+
"bottom",
|
|
1185
|
+
"right"
|
|
1186
|
+
], l = c.map((t) => _(e, t)).join("");
|
|
1187
|
+
l && (o += `<w:tcBorders>${l}</w:tcBorders>`);
|
|
1188
|
+
let u = c.map((e) => X(i[`padding-${e}`]) === void 0 ? "" : `<w:${e} w:w="${Math.max(0, X(i[`padding-${e}`]))}" w:type="dxa"/>`).join("");
|
|
1189
|
+
u && (o += `<w:tcMar>${u}</w:tcMar>`);
|
|
1190
|
+
let d = Math.max(1, a - Math.max(0, X(i["padding-left"]) ?? 0) - Math.max(0, X(i["padding-right"]) ?? 0)), f = y(e.childNodes, Q(i), void 0, {
|
|
1191
|
+
width: d,
|
|
1192
|
+
cell: !0
|
|
1193
|
+
});
|
|
1194
|
+
return (!f || f.endsWith("</w:tbl>")) && (f += g), `<w:tc><w:tcPr>${o}</w:tcPr>${f}</w:tc>`;
|
|
1195
|
+
}).join("") || `<w:tc>${g}</w:tc>`}</w:tr>`).join(""), b = h.map((e) => `<w:gridCol w:w="${e}"/>`).join(""), x = c !== void 0 && !l && !u ? `<w:tblW w:w="${Math.round(c * 50)}" w:type="pct"/>` : `<w:tblW w:w="${f}" w:type="dxa"/>`, S = [
|
|
914
1196
|
"top",
|
|
915
1197
|
"left",
|
|
916
1198
|
"bottom",
|
|
917
1199
|
"right"
|
|
918
|
-
].map((t) =>
|
|
919
|
-
return `<w:tbl><w:tblPr>${
|
|
1200
|
+
].map((t) => _(e, t)).join(""), C = n["table-layout"] === "auto" ? "autofit" : "fixed";
|
|
1201
|
+
return `<w:tbl><w:tblPr>${x}${l ? `<w:tblInd w:w="${l}" w:type="dxa"/>` : ""}${S ? `<w:tblBorders>${S}</w:tblBorders>` : ""}<w:tblLayout w:type="${C}"/></w:tblPr><w:tblGrid>${b}</w:tblGrid>${v}</w:tbl>`;
|
|
920
1202
|
}
|
|
921
|
-
function
|
|
922
|
-
let
|
|
923
|
-
|
|
1203
|
+
function y(e, n, i, c = r) {
|
|
1204
|
+
let l = "", u = [], d = 0, f = Array.from(e).filter((e) => e.nodeType !== 3 || e.textContent), p = (e, t = e) => ({
|
|
1205
|
+
...c,
|
|
1206
|
+
before: e === 0 ? c.before : void 0,
|
|
1207
|
+
after: t === f.length - 1 ? c.after : void 0
|
|
1208
|
+
}), m = (e) => {
|
|
1209
|
+
u.length && (l += g(u, n, i, p(d, e))), u = [];
|
|
924
1210
|
};
|
|
925
|
-
for (let
|
|
926
|
-
if (!(
|
|
927
|
-
|
|
1211
|
+
for (let [e, r] of f.entries()) {
|
|
1212
|
+
if (!(r instanceof Element) || !xe.has(r.localName)) {
|
|
1213
|
+
u.length || (d = e), u.push(r);
|
|
928
1214
|
continue;
|
|
929
1215
|
}
|
|
930
|
-
|
|
931
|
-
let
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1216
|
+
m(e - 1);
|
|
1217
|
+
let f = Z(r, Q(n)), h = {
|
|
1218
|
+
...p(e),
|
|
1219
|
+
htmlPath: s.get(r)
|
|
1220
|
+
};
|
|
1221
|
+
if (r.localName === "table") l += v(r, f, h);
|
|
1222
|
+
else if (r.localName === "ol" || r.localName === "ul") {
|
|
1223
|
+
let e = a++;
|
|
1224
|
+
o.push({
|
|
1225
|
+
id: e,
|
|
1226
|
+
tag: r.localName
|
|
1227
|
+
}), i && M(t, "nested-list-normalized", "Вложенный список при открытии становится отдельным списком.", "loss");
|
|
1228
|
+
let n = Array.from(r.children).filter((e) => e.localName === "li");
|
|
1229
|
+
for (let [t, r] of n.entries()) {
|
|
1230
|
+
let i = {
|
|
1231
|
+
id: e,
|
|
942
1232
|
pending: !0
|
|
1233
|
+
}, a = Z(r, Q(f)), o = {
|
|
1234
|
+
...h,
|
|
1235
|
+
before: t === 0 ? h.before : void 0,
|
|
1236
|
+
after: t === n.length - 1 ? h.after : void 0,
|
|
1237
|
+
left: (h.left ?? 0) + (X(f["margin-left"]) ?? 0),
|
|
1238
|
+
right: (h.right ?? 0) + (X(f["margin-right"]) ?? 0)
|
|
943
1239
|
};
|
|
944
|
-
|
|
1240
|
+
l += y(r.childNodes, a, i, o) || g([], a, i, o);
|
|
945
1241
|
}
|
|
946
|
-
} else
|
|
1242
|
+
} else r.localName === "div" && Array.from(r.children).some((e) => xe.has(e.localName)) ? (f["page-break-before"] === "always" && (l += g([], {
|
|
947
1243
|
"page-break-before": "always",
|
|
948
1244
|
"margin-bottom": "0pt"
|
|
949
|
-
})),
|
|
1245
|
+
})), l += y(r.childNodes, Q(f), i, {
|
|
1246
|
+
...h,
|
|
1247
|
+
left: (h.left ?? 0) + (X(f["margin-left"]) ?? 0),
|
|
1248
|
+
right: (h.right ?? 0) + (X(f["margin-right"]) ?? 0),
|
|
1249
|
+
before: Math.max(h.before ?? 0, X(f["margin-top"]) ?? 0),
|
|
1250
|
+
after: Math.max(h.after ?? 0, X(f["margin-bottom"]) ?? 0)
|
|
1251
|
+
}), f["page-break-after"] === "always" && (l += g([], {
|
|
950
1252
|
"page-break-before": "always",
|
|
951
1253
|
"margin-bottom": "0pt"
|
|
952
|
-
}))) :
|
|
1254
|
+
}))) : r.localName === "hr" ? (M(t, "rule-normalized", "Разделитель HTML преобразован в строку."), l += g([document.createTextNode("────────────────")], f, void 0, c)) : l += g(r.childNodes, f, i, h);
|
|
953
1255
|
}
|
|
954
|
-
return
|
|
1256
|
+
return m(f.length - 1), l;
|
|
955
1257
|
}
|
|
956
|
-
let
|
|
957
|
-
if (new TextEncoder().encode(
|
|
958
|
-
let
|
|
959
|
-
for (let e of
|
|
1258
|
+
let b = y(i.childNodes, f) || "<w:p/>";
|
|
1259
|
+
if (new TextEncoder().encode(b).byteLength > 8387584) throw new A("После преобразования HTML документ превышает допустимый размер XML (8 МиБ).");
|
|
1260
|
+
let x = 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(" "));
|
|
1261
|
+
for (let e of i.querySelectorAll("[style]")) for (let n of Array.from(e.style)) {
|
|
960
1262
|
let r = e.style.getPropertyValue(n), i = ["td", "th"].includes(e.localName);
|
|
961
|
-
|
|
1263
|
+
n === "vertical-align" && !i && ![
|
|
1264
|
+
"baseline",
|
|
1265
|
+
"sub",
|
|
1266
|
+
"super"
|
|
1267
|
+
].includes(r) && M(t, "baseline-shift-lost", "Вертикальное смещение HTML-фрагмента не представлено в DOCX-адаптере.", "loss", {
|
|
1268
|
+
stage: "import",
|
|
1269
|
+
location: { htmlPath: s.get(e) },
|
|
1270
|
+
before: r,
|
|
1271
|
+
after: "baseline"
|
|
1272
|
+
}), (n.startsWith("padding") && !i || n.startsWith("border") && !i && e.localName !== "table" || n === "font-size" && Y(r) === void 0 || ["color", "background-color"].includes(n) && J(r) === void 0 || !x.has(n) && !/^border-(top|right|bottom|left)-(width|style|color)$/.test(n)) && M(t, "html-style-approximation", `Стиль ${n} может измениться при открытии HTML в DOCX-редакторе.`, "warning", {
|
|
1273
|
+
stage: "import",
|
|
1274
|
+
location: { htmlPath: s.get(e) },
|
|
1275
|
+
before: r
|
|
1276
|
+
});
|
|
962
1277
|
}
|
|
963
|
-
let
|
|
964
|
-
|
|
1278
|
+
let S = new p();
|
|
1279
|
+
S.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>"), S.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>"), S.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>");
|
|
1280
|
+
let C = n.page;
|
|
1281
|
+
return S.file("word/document.xml", `<w:document xmlns:w="${R}"><w:body>${b}<w:sectPr><w:pgSz w:w="${C.widthTwips}" w:h="${C.heightTwips}" w:orient="${C.orientation}"/><w:pgMar ${Object.entries(C.margins).map(([e, t]) => `w:${e}="${t}"`).join(" ")}/></w:sectPr></w:body></w:document>`), S.file("word/styles.xml", `<w:styles xmlns:w="${R}"><w:docDefaults><w:rPrDefault><w:rPr>${m(f)}</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>`), S.file("word/numbering.xml", `<w:numbering xmlns:w="${R}">${o.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 S.generateAsync({
|
|
965
1282
|
type: "arraybuffer",
|
|
966
1283
|
compression: "DEFLATE"
|
|
967
1284
|
}));
|
|
968
1285
|
}
|
|
969
1286
|
//#endregion
|
|
970
1287
|
//#region src/library/hujjat/docx.ts
|
|
971
|
-
async function
|
|
972
|
-
let n = await
|
|
973
|
-
return r.warnings.unshift(...n.warnings),
|
|
1288
|
+
async function we(e, t) {
|
|
1289
|
+
let n = await ve(e, t.layout), r = ce(t.locales ?? {}, t.locale, n.html);
|
|
1290
|
+
return r.warnings.unshift(...n.warnings), r.layout = n.layout, N(r.warnings, t.allowLossy), r;
|
|
974
1291
|
}
|
|
975
|
-
async function
|
|
976
|
-
let r =
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1292
|
+
async function Te(e, t, n = {}) {
|
|
1293
|
+
let r = E(n.layout), i = oe(se(e, t));
|
|
1294
|
+
D(r.page, E().page) || M(i.warnings, "layout-not-carried-by-html", "Размеры и поля страницы переданы отдельно в layout. Старый HTML/PDF-контракт их не применяет.", "warning", { stage: "import" });
|
|
1295
|
+
let a = await Ce(i.html, i.warnings, r);
|
|
1296
|
+
return N(i.warnings, n.allowLossy), {
|
|
1297
|
+
...i,
|
|
1298
|
+
document: a,
|
|
1299
|
+
layout: r
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
//#endregion
|
|
1303
|
+
//#region src/library/document-diagnostics.ts
|
|
1304
|
+
async function Ee(e) {
|
|
1305
|
+
if (e.byteLength > 31457280) throw new A("DOCX превышает 30 МиБ.");
|
|
1306
|
+
let t = await p.loadAsync(e);
|
|
1307
|
+
if (Object.keys(t.files).length > 2e3) throw new A("В DOCX более 2000 частей.");
|
|
1308
|
+
let [n, r] = await Promise.all([K(t, "word/document.xml"), K(t, "word/styles.xml")]), i = V(n?.documentElement, "body");
|
|
1309
|
+
if (!i) throw new A("Нет структуры документа Word.");
|
|
1310
|
+
let a = [], o = V(r?.documentElement, "docDefaults"), s = V(V(o, "pPrDefault"), "pPr"), c = q(V(V(o, "rPrDefault"), "rPr")), l = new Map(B(r?.documentElement, "style").map((e) => [H(e, "styleId"), e])), u = B(r?.documentElement, "style").find((e) => H(e, "type") === "paragraph" && H(e, "default") === "1");
|
|
1311
|
+
function d(e, t = /* @__PURE__ */ new Set()) {
|
|
1312
|
+
if (!e || t.has(e) || t.size >= 30) return [];
|
|
1313
|
+
t.add(e);
|
|
1314
|
+
let n = l.get(e);
|
|
1315
|
+
return n ? [...d(U(n, "basedOn"), t), n] : [];
|
|
1316
|
+
}
|
|
1317
|
+
let f = Array.from(i.getElementsByTagNameNS(R, "sectPr")), m = (e) => [V(e, "pgSz"), V(e, "pgMar")].map((e) => Array.from(e?.attributes ?? []).map((e) => [e.localName, e.value]).sort()).flat();
|
|
1318
|
+
return f.forEach((e, t) => {
|
|
1319
|
+
t && JSON.stringify(m(e)) !== JSON.stringify(m(f[0])) && M(a, "source-section-layout", "Раздел использует другую геометрию. Она сохраняется в DOCX; единый профиль HTML её не описывает.", "warning", {
|
|
1320
|
+
stage: "import",
|
|
1321
|
+
location: {
|
|
1322
|
+
part: "word/document.xml",
|
|
1323
|
+
sectionIndex: t
|
|
1324
|
+
},
|
|
1325
|
+
before: JSON.stringify(m(e)),
|
|
1326
|
+
after: JSON.stringify(m(e))
|
|
1327
|
+
});
|
|
1328
|
+
}), Array.from(i.getElementsByTagNameNS(R, "p")).forEach((e, t) => {
|
|
1329
|
+
let n = {
|
|
1330
|
+
part: "word/document.xml",
|
|
1331
|
+
paragraphIndex: t
|
|
1332
|
+
}, r = V(e, "pPr"), i = d(U(r, "pStyle") || H(u, "styleId")), o = he([
|
|
1333
|
+
s,
|
|
1334
|
+
...i.map((e) => V(e, "pPr")),
|
|
1335
|
+
r
|
|
1336
|
+
]), l = Object.assign({}, c, ...i.map((e) => q(V(e, "rPr")))), f = _e(l);
|
|
1337
|
+
Array.from(e.getElementsByTagNameNS(R, "r")).forEach((e, t) => {
|
|
1338
|
+
let r = V(e, "rPr"), i = Object.assign({}, l, ...d(U(r, "rStyle")).map((e) => q(V(e, "rPr"))), q(r));
|
|
1339
|
+
i["--az-hidden"] !== "1" && (f = Math.max(f, _e(i)), Number(i["--az-position"]) && M(a, "source-baseline-shift", "Исходный фрагмент смещён по вертикали; сохранён без нормализации.", "warning", {
|
|
1340
|
+
stage: "import",
|
|
1341
|
+
location: {
|
|
1342
|
+
...n,
|
|
1343
|
+
runIndex: t
|
|
1344
|
+
},
|
|
1345
|
+
before: Number(i["--az-position"]) / 2,
|
|
1346
|
+
after: Number(i["--az-position"]) / 2
|
|
1347
|
+
}));
|
|
1348
|
+
}), o && (o.rule === "auto" ? o.value < 240 : o.value / 20 < f) && M(a, "source-tight-spacing", "Авторский тесный интервал сохранён. Проверьте наложение строк на используемых шрифтах.", "warning", {
|
|
1349
|
+
stage: "import",
|
|
1350
|
+
location: n,
|
|
1351
|
+
before: `${o.rule}:${o.value}`,
|
|
1352
|
+
after: `${o.rule}:${o.value}`
|
|
1353
|
+
}), [...Array.from(e.getElementsByTagNameNS("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "t")).map((e) => e.textContent ?? "").join("").matchAll(/\{([^{}]+)\}/g)].some((e) => !P(e[1])) && M(a, "invalid-variable", "В абзаце есть некорректный ключ переменной. Имя и исходный текст не изменены.", "warning", {
|
|
1354
|
+
stage: "import",
|
|
1355
|
+
location: n
|
|
1356
|
+
});
|
|
1357
|
+
}), a;
|
|
1358
|
+
}
|
|
1359
|
+
//#endregion
|
|
1360
|
+
//#region src/library/font-diagnostics.ts
|
|
1361
|
+
function De(e) {
|
|
1362
|
+
let t = 0, n = !1, r = !1, i = 0, a = [], o = /* @__PURE__ */ new Set(), s = {
|
|
1363
|
+
state: typeof e == "function" ? "loading" : "unknown",
|
|
1364
|
+
warnings: []
|
|
1365
|
+
}, c = () => {
|
|
1366
|
+
s = {
|
|
1367
|
+
state: t ? "loading" : r || a.length ? "degraded" : n ? "ready" : "unknown",
|
|
1368
|
+
warnings: [...a]
|
|
1369
|
+
}, o.forEach((e) => e());
|
|
1370
|
+
}, l = (e, t) => {
|
|
1371
|
+
if (e) {
|
|
1372
|
+
n ||= !!e.sources?.some((e) => e.bytes.byteLength && e.availability !== "forbidden");
|
|
1373
|
+
for (let n of e.substitutions ?? []) {
|
|
1374
|
+
if (t && !t.some((e) => e.toLowerCase() === n.from.family.toLowerCase())) continue;
|
|
1375
|
+
let r = (e, t) => e.family.toLowerCase() === t.family.toLowerCase() && e.weight === t.weight && e.style === t.style;
|
|
1376
|
+
if (e.sources?.some((e) => r(e.request, n.from) && e.bytes.byteLength && e.availability !== "forbidden")) continue;
|
|
1377
|
+
let i = (e) => `${e.family} (${e.weight}, ${e.style})`;
|
|
1378
|
+
M(a, "font-redirect", "Настроена подстановка начертания шрифта. Сравните её с источником и PDF.", "warning", {
|
|
1379
|
+
stage: "fonts",
|
|
1380
|
+
before: i(n.from),
|
|
1381
|
+
after: i(n.to)
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}, u = (e) => {
|
|
1386
|
+
r = !0, M(a, "font-load-failed", `Не удалось подготовить шрифт (${e}). Разметка может использовать замену или оценочные метрики.`, "warning", { stage: "fonts" }), c();
|
|
1387
|
+
}, d = typeof e == "function" ? m(async (n) => {
|
|
1388
|
+
let r = i;
|
|
1389
|
+
t++, c();
|
|
1390
|
+
try {
|
|
1391
|
+
let t = await e(n);
|
|
1392
|
+
return r === i && !n.signal?.aborted && l(t, [...n.families, n.defaultFamily]), t;
|
|
1393
|
+
} catch (e) {
|
|
1394
|
+
throw r === i && !n.signal?.aborted && u("resolver"), e;
|
|
1395
|
+
} finally {
|
|
1396
|
+
r === i && (t--, c());
|
|
1397
|
+
}
|
|
1398
|
+
}) : e;
|
|
1399
|
+
return typeof e != "function" && (l(e), c()), {
|
|
1400
|
+
fonts: d,
|
|
1401
|
+
snapshot: () => s,
|
|
1402
|
+
subscribe: (e) => (o.add(e), () => {
|
|
1403
|
+
o.delete(e);
|
|
1404
|
+
}),
|
|
1405
|
+
fail: u,
|
|
1406
|
+
reset: () => {
|
|
1407
|
+
i++, t = 0, n = !1, r = !1, a.length = 0, typeof e == "function" ? (s = {
|
|
1408
|
+
state: "loading",
|
|
1409
|
+
warnings: []
|
|
1410
|
+
}, o.forEach((e) => e())) : (l(e), c());
|
|
1411
|
+
}
|
|
980
1412
|
};
|
|
981
1413
|
}
|
|
982
1414
|
//#endregion
|
|
983
1415
|
//#region src/library/AzDocumentEditor.tsx
|
|
984
|
-
var
|
|
985
|
-
function
|
|
986
|
-
let
|
|
1416
|
+
var Oe = () => {};
|
|
1417
|
+
function ke({ onStatusChange: e, fonts: t }) {
|
|
1418
|
+
let r = o(e);
|
|
1419
|
+
i(() => {
|
|
1420
|
+
r.current = e;
|
|
1421
|
+
});
|
|
1422
|
+
let s = u((e) => e.page.total), c = u((e) => e.isLoading || !!e.isOpening) || t.state === "loading", l = u((e) => e.parseError), d = u((e) => e.fontSubstitutions), f = a(() => {
|
|
1423
|
+
let e = [...t.warnings, ...(d ?? []).map((e) => ({
|
|
1424
|
+
code: "font-unavailable",
|
|
1425
|
+
message: `Шрифт ${e} недоступен движку.`,
|
|
1426
|
+
severity: "warning",
|
|
1427
|
+
stage: "fonts",
|
|
1428
|
+
before: e
|
|
1429
|
+
}))];
|
|
1430
|
+
return {
|
|
1431
|
+
state: c ? "loading" : e.length ? "degraded" : t.state,
|
|
1432
|
+
warnings: e
|
|
1433
|
+
};
|
|
1434
|
+
}, [
|
|
1435
|
+
t,
|
|
1436
|
+
d,
|
|
1437
|
+
c
|
|
1438
|
+
]);
|
|
987
1439
|
return n(() => {
|
|
988
|
-
|
|
989
|
-
pages:
|
|
990
|
-
loading:
|
|
991
|
-
error:
|
|
1440
|
+
r.current?.({
|
|
1441
|
+
pages: s,
|
|
1442
|
+
loading: c,
|
|
1443
|
+
error: l,
|
|
1444
|
+
fonts: f
|
|
992
1445
|
});
|
|
993
1446
|
}, [
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1447
|
+
s,
|
|
1448
|
+
c,
|
|
1449
|
+
l,
|
|
1450
|
+
f
|
|
998
1451
|
]), null;
|
|
999
1452
|
}
|
|
1000
|
-
var
|
|
1001
|
-
let
|
|
1002
|
-
|
|
1003
|
-
|
|
1453
|
+
var Ae = e(function(e, t) {
|
|
1454
|
+
let u = o(null), p = o(null), m = o(null), [v, y] = s(""), b = a(() => f(), []), C = d(b), w = e.fonts ?? C, T = a(() => De(w), [w]), E = c(T.subscribe, T.snapshot, T.snapshot), D = o(e), O = o(0), k = o(!1), j = o(T);
|
|
1455
|
+
i(() => {
|
|
1456
|
+
D.current = e, j.current = T;
|
|
1457
|
+
}), i(() => {
|
|
1458
|
+
T.reset();
|
|
1459
|
+
}, [T, e.document]);
|
|
1460
|
+
async function M(e, t) {
|
|
1461
|
+
if (!D.current.onDiagnostics) return;
|
|
1462
|
+
let n;
|
|
1463
|
+
try {
|
|
1464
|
+
n = await Ee(e);
|
|
1465
|
+
} catch {
|
|
1466
|
+
n = [{
|
|
1467
|
+
code: "diagnostics-unavailable",
|
|
1468
|
+
message: "Не удалось проанализировать оформление исходного DOCX.",
|
|
1469
|
+
severity: "warning",
|
|
1470
|
+
stage: "import"
|
|
1471
|
+
}];
|
|
1472
|
+
}
|
|
1473
|
+
k.current && t === O.current && D.current.onDiagnostics?.(n);
|
|
1474
|
+
}
|
|
1475
|
+
n(() => {
|
|
1476
|
+
k.current = !0;
|
|
1477
|
+
let t = ++O.current;
|
|
1478
|
+
return D.current.onDiagnostics?.([]), e.document && e.document !== "blank" && M(e.document, t), () => {
|
|
1479
|
+
k.current = !1, ++O.current;
|
|
1480
|
+
};
|
|
1481
|
+
}, [e.document]);
|
|
1482
|
+
let N = (t) => e.ui !== !1 && e.ui?.[t] !== !1;
|
|
1483
|
+
function F(e) {
|
|
1484
|
+
let t = p.current?.querySelector("[data-menu=\"file\"] > [role=\"menuitem\"][aria-expanded=\"true\"]");
|
|
1004
1485
|
t?.click(), t?.focus(), e();
|
|
1005
1486
|
}
|
|
1006
|
-
async function
|
|
1007
|
-
let t =
|
|
1008
|
-
if (!t || !
|
|
1009
|
-
|
|
1487
|
+
async function I() {
|
|
1488
|
+
let t = u.current?.getEditor();
|
|
1489
|
+
if (!t || !p.current || t.snapshot().isLoading || t.snapshot().parseError || window.document.querySelector("[data-az-print-root]")) return;
|
|
1490
|
+
m.current?.abort();
|
|
1010
1491
|
let n = new AbortController();
|
|
1011
|
-
|
|
1492
|
+
m.current = n, y("");
|
|
1012
1493
|
try {
|
|
1013
|
-
await
|
|
1494
|
+
await S(t, p.current, e.title ?? "Документ.docx", n.signal);
|
|
1014
1495
|
} catch (e) {
|
|
1015
|
-
!n.signal.aborted && !(e instanceof DOMException && e.name === "AbortError") &&
|
|
1496
|
+
!n.signal.aborted && !(e instanceof DOMException && e.name === "AbortError") && y(e instanceof Error ? e.message : "Не удалось подготовить PDF.");
|
|
1016
1497
|
}
|
|
1017
1498
|
}
|
|
1018
|
-
return n(() => () =>
|
|
1499
|
+
return n(() => () => m.current?.abort(), []), n(() => {
|
|
1019
1500
|
let t = (t) => {
|
|
1020
|
-
if (t.defaultPrevented || !(t.ctrlKey || t.metaKey) || t.altKey || t.shiftKey || !
|
|
1021
|
-
let n = t.code === "KeyS" ? e.onSave : t.code === "KeyO" ? e.onOpen : t.code === "KeyP" &&
|
|
1501
|
+
if (t.defaultPrevented || !(t.ctrlKey || t.metaKey) || t.altKey || t.shiftKey || !p.current || !x(p.current, t.target) || window.document.querySelector("[data-az-print-root]") || t.code !== "KeyS" && t.code !== "KeyO" && !(t.code === "KeyP" && N("print"))) return;
|
|
1502
|
+
let n = t.code === "KeyS" ? e.onSave : t.code === "KeyO" ? e.onOpen : t.code === "KeyP" && N("print") ? () => void I() : void 0;
|
|
1022
1503
|
t.preventDefault(), t.stopImmediatePropagation(), e.actionsDisabled || n?.();
|
|
1023
1504
|
};
|
|
1024
1505
|
return window.addEventListener("keydown", t, !0), () => window.removeEventListener("keydown", t, !0);
|
|
1025
1506
|
}), r(t, () => ({
|
|
1026
1507
|
async save() {
|
|
1027
|
-
let e = await
|
|
1028
|
-
if (!
|
|
1029
|
-
return e;
|
|
1508
|
+
let e = O.current, t = await u.current?.save();
|
|
1509
|
+
if (!t) throw Error("Документ ещё не готов к сохранению.");
|
|
1510
|
+
return M(t, e), t;
|
|
1030
1511
|
},
|
|
1031
1512
|
async exportHujjat(e) {
|
|
1032
|
-
let t = await
|
|
1033
|
-
if (!t) throw new
|
|
1034
|
-
return
|
|
1513
|
+
let t = await u.current?.save();
|
|
1514
|
+
if (!t) throw new A("Документ ещё не готов к экспорту.");
|
|
1515
|
+
return we(t, e);
|
|
1035
1516
|
},
|
|
1036
1517
|
insertVariable(e) {
|
|
1037
|
-
if (!
|
|
1038
|
-
let t =
|
|
1518
|
+
if (!P(e)) throw new A("Некорректный ключ переменной. Используйте client.name, ASCII, до 100 символов.");
|
|
1519
|
+
let t = u.current?.exec({
|
|
1039
1520
|
type: "pasteWithoutFormatting",
|
|
1040
1521
|
text: `{${e}}`
|
|
1041
1522
|
});
|
|
1042
|
-
if (!t?.ok) throw new
|
|
1043
|
-
|
|
1523
|
+
if (!t?.ok) throw new A(t && !t.ok ? t.reason : "Редактор ещё не готов.");
|
|
1524
|
+
u.current?.focus();
|
|
1525
|
+
},
|
|
1526
|
+
setParagraphPagination(t) {
|
|
1527
|
+
let n = u.current?.getEditor()?.snapshot();
|
|
1528
|
+
if (!n || n.isLoading || n.isOpening || n.parseError || E.state === "loading" || e.mode === "view" || e.actionsDisabled) throw new A("Редактор недоступен для изменения.");
|
|
1529
|
+
let r = {};
|
|
1530
|
+
for (let e of [
|
|
1531
|
+
"keepNext",
|
|
1532
|
+
"keepLines",
|
|
1533
|
+
"widowControl",
|
|
1534
|
+
"pageBreakBefore"
|
|
1535
|
+
]) if (t[e] !== void 0) {
|
|
1536
|
+
if (typeof t[e] != "boolean") throw new A("Правила абзаца должны быть boolean.");
|
|
1537
|
+
r[e] = t[e];
|
|
1538
|
+
}
|
|
1539
|
+
if (!Object.keys(r).length) return;
|
|
1540
|
+
let i = u.current.exec({
|
|
1541
|
+
type: "setParagraphFormat",
|
|
1542
|
+
...r
|
|
1543
|
+
});
|
|
1544
|
+
if (!i.ok) throw new A(i.reason);
|
|
1545
|
+
u.current?.focus();
|
|
1044
1546
|
},
|
|
1045
1547
|
focus() {
|
|
1046
|
-
|
|
1548
|
+
u.current?.focus();
|
|
1047
1549
|
},
|
|
1048
|
-
print:
|
|
1049
|
-
})), /* @__PURE__ */
|
|
1550
|
+
print: I
|
|
1551
|
+
})), /* @__PURE__ */ g("div", {
|
|
1050
1552
|
className: ["az-document-editor", e.className].filter(Boolean).join(" "),
|
|
1051
1553
|
style: e.style,
|
|
1052
|
-
ref:
|
|
1053
|
-
children: [
|
|
1554
|
+
ref: p,
|
|
1555
|
+
children: [v && /* @__PURE__ */ h("div", {
|
|
1054
1556
|
role: "alert",
|
|
1055
1557
|
className: "az-print-error",
|
|
1056
|
-
children:
|
|
1057
|
-
}), /* @__PURE__ */
|
|
1058
|
-
ref:
|
|
1558
|
+
children: v
|
|
1559
|
+
}), /* @__PURE__ */ h(l, {
|
|
1560
|
+
ref: u,
|
|
1059
1561
|
document: e.document ?? "blank",
|
|
1060
1562
|
title: e.title ?? "Документ.docx",
|
|
1061
|
-
fonts:
|
|
1563
|
+
fonts: T.fonts,
|
|
1062
1564
|
locale: e.locale ?? "ru-RU",
|
|
1063
|
-
i18n: e.i18n ??
|
|
1565
|
+
i18n: e.i18n ?? _,
|
|
1064
1566
|
mode: e.mode ?? "edit",
|
|
1065
1567
|
colorMode: e.colorMode ?? "light",
|
|
1066
1568
|
zoom: e.zoom,
|
|
1067
1569
|
zoomMode: e.zoomMode,
|
|
1068
|
-
chrome:
|
|
1069
|
-
rulers:
|
|
1070
|
-
navigation:
|
|
1071
|
-
contextMenu:
|
|
1570
|
+
chrome: N("chrome"),
|
|
1571
|
+
rulers: N("rulers"),
|
|
1572
|
+
navigation: N("navigation"),
|
|
1573
|
+
contextMenu: N("contextMenu"),
|
|
1072
1574
|
renderTitleBarLeft: e.renderTitleBarLeft,
|
|
1073
1575
|
renderTitleBarRight: e.renderTitleBarRight,
|
|
1074
1576
|
onChange: (t) => {
|
|
1075
|
-
t.source || e.onChange?.();
|
|
1577
|
+
t.source || (++O.current, D.current.onDiagnostics?.([]), e.onChange?.());
|
|
1076
1578
|
},
|
|
1077
1579
|
onSave: e.onSave,
|
|
1078
1580
|
onOpen: e.onOpen,
|
|
1079
|
-
onFontError: (
|
|
1080
|
-
|
|
1581
|
+
onFontError: (e) => {
|
|
1582
|
+
j.current === T && k.current && (T.fail(e.code), D.current.onFontError?.(`Не удалось загрузить шрифт (${e.code}). Переносы могут отличаться от Word.`));
|
|
1583
|
+
},
|
|
1584
|
+
menu: N("menu") && {
|
|
1081
1585
|
reportIssue: !1,
|
|
1082
|
-
onOpen:
|
|
1083
|
-
onSave:
|
|
1084
|
-
children: /* @__PURE__ */
|
|
1586
|
+
onOpen: Oe,
|
|
1587
|
+
onSave: Oe,
|
|
1588
|
+
children: /* @__PURE__ */ g(l.Menu.File, {
|
|
1085
1589
|
preset: !1,
|
|
1086
1590
|
children: [
|
|
1087
|
-
e.fileActions?.map((t) => /* @__PURE__ */
|
|
1088
|
-
onSelect: () =>
|
|
1591
|
+
e.fileActions?.map((t) => /* @__PURE__ */ h(l.Menu.Row, {
|
|
1592
|
+
onSelect: () => F(t.onSelect),
|
|
1089
1593
|
disabled: e.actionsDisabled || t.disabled,
|
|
1090
1594
|
children: t.label
|
|
1091
1595
|
}, t.id)),
|
|
1092
|
-
e.onOpen && /* @__PURE__ */
|
|
1093
|
-
onSelect: () =>
|
|
1596
|
+
e.onOpen && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1597
|
+
onSelect: () => F(e.onOpen),
|
|
1094
1598
|
disabled: e.actionsDisabled,
|
|
1095
1599
|
shortcut: "Ctrl+O",
|
|
1096
|
-
children: e.labels?.open ?? e.i18n?.toolbar?.open ??
|
|
1600
|
+
children: e.labels?.open ?? e.i18n?.toolbar?.open ?? _.toolbar?.open
|
|
1097
1601
|
}),
|
|
1098
|
-
e.onSave && /* @__PURE__ */
|
|
1099
|
-
onSelect: () =>
|
|
1602
|
+
e.onSave && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1603
|
+
onSelect: () => F(e.onSave),
|
|
1100
1604
|
disabled: e.actionsDisabled,
|
|
1101
1605
|
shortcut: "Ctrl+S",
|
|
1102
|
-
children: e.labels?.save ?? e.i18n?.toolbar?.save ??
|
|
1606
|
+
children: e.labels?.save ?? e.i18n?.toolbar?.save ?? _.toolbar?.save
|
|
1103
1607
|
}),
|
|
1104
|
-
e.onExportPdf && /* @__PURE__ */
|
|
1105
|
-
onSelect: () =>
|
|
1608
|
+
e.onExportPdf && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1609
|
+
onSelect: () => F(e.onExportPdf),
|
|
1106
1610
|
disabled: e.actionsDisabled,
|
|
1107
1611
|
children: e.labels?.exportPdf ?? "Скачать PDF"
|
|
1108
1612
|
}),
|
|
1109
|
-
|
|
1110
|
-
onSelect: () =>
|
|
1613
|
+
N("print") && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1614
|
+
onSelect: () => F(() => void I()),
|
|
1111
1615
|
disabled: e.actionsDisabled,
|
|
1112
1616
|
shortcut: "Ctrl+P",
|
|
1113
1617
|
children: e.labels?.print ?? "Распечатать…"
|
|
1114
1618
|
}),
|
|
1115
|
-
/* @__PURE__ */
|
|
1619
|
+
/* @__PURE__ */ h(l.Menu.PageSetup, {})
|
|
1116
1620
|
]
|
|
1117
1621
|
})
|
|
1118
1622
|
},
|
|
1119
|
-
children: /* @__PURE__ */
|
|
1623
|
+
children: /* @__PURE__ */ h(ke, {
|
|
1624
|
+
onStatusChange: e.onStatusChange,
|
|
1625
|
+
fonts: E
|
|
1626
|
+
})
|
|
1120
1627
|
})]
|
|
1121
1628
|
});
|
|
1122
1629
|
});
|
|
1123
1630
|
//#endregion
|
|
1124
1631
|
//#region src/library/AzHtmlEditor.tsx
|
|
1125
|
-
function
|
|
1632
|
+
function je(...e) {
|
|
1126
1633
|
let t = /* @__PURE__ */ new Map();
|
|
1127
1634
|
for (let n of e.flat()) t.set(JSON.stringify(n), n);
|
|
1128
1635
|
return [...t.values()];
|
|
1129
1636
|
}
|
|
1130
|
-
var
|
|
1131
|
-
let { initialHtml: c,
|
|
1637
|
+
var Me = e(function(e, a) {
|
|
1638
|
+
let { initialHtml: c, layout: l, onChange: u, onStatusChange: d, renderFallback: f, ...p } = e, [m] = s(c), [_] = s(() => l ? {
|
|
1639
|
+
...l,
|
|
1640
|
+
page: l.page ? {
|
|
1641
|
+
...l.page,
|
|
1642
|
+
margins: { ...l.page.margins }
|
|
1643
|
+
} : void 0
|
|
1644
|
+
} : void 0), [v, y] = s(), [b, x] = s({
|
|
1132
1645
|
phase: "loading",
|
|
1133
1646
|
dirty: !1,
|
|
1134
1647
|
pages: 0,
|
|
1135
1648
|
error: null,
|
|
1136
1649
|
warnings: []
|
|
1137
|
-
}),
|
|
1650
|
+
}), S = o(b), C = o(null), w = o(null), T = o(!1), E = o(0), D = o(0), O = o(e);
|
|
1138
1651
|
i(() => {
|
|
1139
1652
|
O.current = e;
|
|
1140
1653
|
});
|
|
1141
1654
|
let k = t((e) => {
|
|
1142
|
-
|
|
1143
|
-
...
|
|
1655
|
+
T.current && (S.current = {
|
|
1656
|
+
...S.current,
|
|
1144
1657
|
...e
|
|
1145
|
-
},
|
|
1146
|
-
}, []),
|
|
1658
|
+
}, x(S.current), O.current.onStatusChange?.(S.current));
|
|
1659
|
+
}, []), j = t(async (e = !1) => {
|
|
1147
1660
|
let t = ++E.current;
|
|
1148
1661
|
k({
|
|
1149
1662
|
phase: "loading",
|
|
1150
1663
|
error: null
|
|
1151
1664
|
});
|
|
1152
1665
|
try {
|
|
1153
|
-
let n = await
|
|
1666
|
+
let n = await Te({ uz: { blocks: [{
|
|
1154
1667
|
type: "html",
|
|
1155
|
-
props: { html:
|
|
1156
|
-
}] } }, "uz", {
|
|
1157
|
-
|
|
1158
|
-
|
|
1668
|
+
props: { html: m.trim() ? m : "<p><br></p>" }
|
|
1669
|
+
}] } }, "uz", {
|
|
1670
|
+
allowLossy: e,
|
|
1671
|
+
layout: _
|
|
1672
|
+
});
|
|
1673
|
+
if (!T.current || t !== E.current) return;
|
|
1674
|
+
w.current = n, y(n.document), k({ warnings: n.warnings });
|
|
1159
1675
|
} catch (e) {
|
|
1160
|
-
if (!
|
|
1161
|
-
let n = e instanceof
|
|
1676
|
+
if (!T.current || t !== E.current) return;
|
|
1677
|
+
let n = e instanceof A ? e.warnings : [];
|
|
1162
1678
|
k({
|
|
1163
1679
|
phase: n.some((e) => e.severity === "loss") ? "blocked" : "error",
|
|
1164
1680
|
warnings: n,
|
|
1165
1681
|
error: e instanceof Error ? e.message : String(e)
|
|
1166
1682
|
});
|
|
1167
1683
|
}
|
|
1168
|
-
}, [
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1684
|
+
}, [
|
|
1685
|
+
m,
|
|
1686
|
+
_,
|
|
1687
|
+
k
|
|
1688
|
+
]);
|
|
1689
|
+
n(() => (T.current = !0, j(), () => {
|
|
1690
|
+
T.current = !1, ++E.current;
|
|
1691
|
+
}), [j]);
|
|
1692
|
+
let M = t((e) => {
|
|
1693
|
+
let t = e.error ? "error" : e.loading ? "loading" : S.current.phase === "exporting" ? "exporting" : "ready";
|
|
1174
1694
|
k({
|
|
1175
1695
|
phase: t,
|
|
1176
1696
|
pages: e.pages,
|
|
1177
|
-
error: e.error
|
|
1697
|
+
error: e.error,
|
|
1698
|
+
fonts: e.fonts
|
|
1178
1699
|
});
|
|
1179
|
-
}, [k]),
|
|
1180
|
-
|
|
1181
|
-
}, [k]),
|
|
1182
|
-
|
|
1700
|
+
}, [k]), P = t(() => {
|
|
1701
|
+
T.current && ["ready", "exporting"].includes(S.current.phase) && (++D.current, k({ dirty: !0 }), O.current.onChange?.());
|
|
1702
|
+
}, [k]), F = t((e) => {
|
|
1703
|
+
T.current && e === E.current && S.current.phase === "exporting" && k({ phase: "ready" });
|
|
1183
1704
|
}, [k]);
|
|
1184
|
-
return r(
|
|
1705
|
+
return r(a, () => ({
|
|
1185
1706
|
async exportHtml(e = {}) {
|
|
1186
|
-
if (!
|
|
1187
|
-
let t =
|
|
1188
|
-
if (!
|
|
1189
|
-
html:
|
|
1707
|
+
if (!T.current || S.current.phase !== "ready" || !w.current || !C.current) throw new A("HTML-редактор ещё не готов или занят.");
|
|
1708
|
+
let t = w.current;
|
|
1709
|
+
if (!S.current.dirty) return {
|
|
1710
|
+
html: m,
|
|
1190
1711
|
variables: [...t.variables],
|
|
1191
1712
|
warnings: [...t.warnings],
|
|
1713
|
+
layout: t.layout ? structuredClone(t.layout) : void 0,
|
|
1192
1714
|
changed: !1
|
|
1193
1715
|
};
|
|
1194
1716
|
let n = E.current, r = D.current;
|
|
@@ -1197,71 +1719,78 @@ var ye = e(function(e, s) {
|
|
|
1197
1719
|
error: null
|
|
1198
1720
|
});
|
|
1199
1721
|
try {
|
|
1200
|
-
let i = await
|
|
1722
|
+
let i = await C.current.exportHujjat({
|
|
1201
1723
|
locale: "uz",
|
|
1202
|
-
allowLossy: !0
|
|
1724
|
+
allowLossy: !0,
|
|
1725
|
+
layout: _
|
|
1203
1726
|
});
|
|
1204
|
-
if (!
|
|
1205
|
-
let a =
|
|
1206
|
-
return k({ warnings: a }),
|
|
1727
|
+
if (!T.current || n !== E.current || r !== D.current) throw new A("Черновик изменился или закрыт во время экспорта. Повторите экспорт актуального документа.");
|
|
1728
|
+
let a = je(t.warnings, i.warnings);
|
|
1729
|
+
return k({ warnings: a }), N(a, e.allowLossy), {
|
|
1207
1730
|
html: i.html,
|
|
1208
1731
|
variables: i.variables,
|
|
1209
1732
|
warnings: a,
|
|
1733
|
+
layout: i.layout,
|
|
1210
1734
|
changed: !0
|
|
1211
1735
|
};
|
|
1212
1736
|
} finally {
|
|
1213
|
-
|
|
1737
|
+
F(n);
|
|
1214
1738
|
}
|
|
1215
1739
|
},
|
|
1216
1740
|
async acceptImportLoss() {
|
|
1217
|
-
if (!
|
|
1218
|
-
await
|
|
1741
|
+
if (!T.current || S.current.phase !== "blocked") throw new A("Нет ожидающего решения об импорте.");
|
|
1742
|
+
await j(!0);
|
|
1219
1743
|
},
|
|
1220
1744
|
insertVariable(e) {
|
|
1221
|
-
if (!
|
|
1222
|
-
|
|
1745
|
+
if (!T.current || S.current.phase !== "ready" || O.current.mode === "view" || !C.current) throw new A("Редактор недоступен для изменения.");
|
|
1746
|
+
C.current.insertVariable(e);
|
|
1223
1747
|
},
|
|
1224
1748
|
focus() {
|
|
1225
|
-
|
|
1749
|
+
C.current?.focus();
|
|
1750
|
+
},
|
|
1751
|
+
setParagraphPagination(e) {
|
|
1752
|
+
if (!T.current || S.current.phase !== "ready" || O.current.mode === "view" || O.current.actionsDisabled || !C.current) throw new A("Редактор недоступен для изменения.");
|
|
1753
|
+
C.current.setParagraphPagination(e);
|
|
1226
1754
|
}
|
|
1227
1755
|
}), [
|
|
1228
|
-
|
|
1229
|
-
|
|
1756
|
+
m,
|
|
1757
|
+
_,
|
|
1758
|
+
j,
|
|
1230
1759
|
k,
|
|
1231
|
-
|
|
1232
|
-
]),
|
|
1233
|
-
...
|
|
1234
|
-
ref:
|
|
1235
|
-
document:
|
|
1760
|
+
F
|
|
1761
|
+
]), v ? /* @__PURE__ */ h(Ae, {
|
|
1762
|
+
...p,
|
|
1763
|
+
ref: C,
|
|
1764
|
+
document: v,
|
|
1236
1765
|
ui: e.ui !== !1 && {
|
|
1237
1766
|
menu: !1,
|
|
1238
1767
|
print: !1,
|
|
1239
1768
|
...e.ui
|
|
1240
1769
|
},
|
|
1241
|
-
mode:
|
|
1242
|
-
actionsDisabled: e.actionsDisabled ||
|
|
1243
|
-
onChange:
|
|
1244
|
-
onStatusChange:
|
|
1245
|
-
}) : /* @__PURE__ */
|
|
1770
|
+
mode: b.phase === "exporting" ? "view" : e.mode,
|
|
1771
|
+
actionsDisabled: e.actionsDisabled || b.phase !== "ready",
|
|
1772
|
+
onChange: P,
|
|
1773
|
+
onStatusChange: M
|
|
1774
|
+
}) : /* @__PURE__ */ h("div", {
|
|
1246
1775
|
className: ["az-html-editor", e.className].filter(Boolean).join(" "),
|
|
1247
1776
|
style: e.style,
|
|
1248
|
-
children:
|
|
1249
|
-
role:
|
|
1250
|
-
children: [
|
|
1777
|
+
children: f ? f(b) : /* @__PURE__ */ g("div", {
|
|
1778
|
+
role: b.error ? "alert" : "status",
|
|
1779
|
+
children: [b.error ?? "Загрузка документа…", b.warnings.length > 0 && /* @__PURE__ */ h("ul", { children: b.warnings.map((e, t) => /* @__PURE__ */ h("li", { children: e.message }, t)) })]
|
|
1251
1780
|
})
|
|
1252
1781
|
});
|
|
1253
|
-
}),
|
|
1254
|
-
function
|
|
1782
|
+
}), Ne = 31457280, Pe = "application/vnd.openxmlformats-officedocument.wordprocessingml.document", Fe = `${Pe}.main+xml`, Ie = 8388608, $ = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
|
|
1783
|
+
function Le(e) {
|
|
1255
1784
|
let t = new DOMParser().parseFromString(e, "application/xml");
|
|
1256
1785
|
if (t.getElementsByTagName("parsererror").length || /<!DOCTYPE/i.test(e)) throw Error("XML документа повреждён или содержит неподдерживаемую структуру.");
|
|
1257
1786
|
return t;
|
|
1258
1787
|
}
|
|
1259
|
-
function
|
|
1788
|
+
function Re(e, t) {
|
|
1260
1789
|
let n = e.file(t);
|
|
1261
1790
|
return n ? new Promise((e, t) => {
|
|
1262
1791
|
let r = n.internalStream("uint8array"), i = [], a = 0;
|
|
1263
1792
|
r.on("data", (e) => {
|
|
1264
|
-
a += e.byteLength, a >
|
|
1793
|
+
a += e.byteLength, a > Ie ? (r.pause(), t(/* @__PURE__ */ Error("Структура документа слишком большая для этого прототипа."))) : i.push(e);
|
|
1265
1794
|
}), r.on("error", t), r.on("end", () => {
|
|
1266
1795
|
let t = new Uint8Array(a), n = 0;
|
|
1267
1796
|
for (let e of i) t.set(e, n), n += e.byteLength;
|
|
@@ -1269,70 +1798,70 @@ function $(e, t) {
|
|
|
1269
1798
|
}), r.resume();
|
|
1270
1799
|
}) : Promise.resolve("");
|
|
1271
1800
|
}
|
|
1272
|
-
async function
|
|
1801
|
+
async function ze(e) {
|
|
1273
1802
|
if (!/\.docx$/i.test(e.name)) throw Error("Откройте файл DOCX. Форматы DOC, DOCM и PDF здесь не поддерживаются.");
|
|
1274
1803
|
if (!e.size) throw Error("Файл DOCX пуст.");
|
|
1275
1804
|
if (e.size > 31457280) throw Error("Максимальный размер DOCX — 30 МБ.");
|
|
1276
1805
|
let t = new Uint8Array(await e.arrayBuffer()), n;
|
|
1277
1806
|
try {
|
|
1278
|
-
n = await
|
|
1807
|
+
n = await p.loadAsync(t);
|
|
1279
1808
|
} catch {
|
|
1280
1809
|
throw Error("Файл повреждён, зашифрован или не является DOCX.");
|
|
1281
1810
|
}
|
|
1282
1811
|
let r = Object.keys(n.files);
|
|
1283
1812
|
if (r.length > 2e3) throw Error("Слишком много вложенных частей в DOCX для этого прототипа.");
|
|
1284
1813
|
if (!n.file("[Content_Types].xml") || !n.file("word/document.xml")) throw Error("Файл не содержит структуру DOCX.");
|
|
1285
|
-
let i =
|
|
1286
|
-
if (Array.from(i.getElementsByTagNameNS("*", "Override")).find((e) => e.getAttribute("PartName") === "/word/document.xml")?.getAttribute("ContentType") !==
|
|
1287
|
-
let a =
|
|
1288
|
-
if (a.documentElement.localName !== "document" || !a.getElementsByTagNameNS(
|
|
1814
|
+
let i = Le(await Re(n, "[Content_Types].xml"));
|
|
1815
|
+
if (Array.from(i.getElementsByTagNameNS("*", "Override")).find((e) => e.getAttribute("PartName") === "/word/document.xml")?.getAttribute("ContentType") !== Fe || r.some((e) => /vbaProject\.bin$/i.test(e))) throw Error("Поддерживается только обычный DOCX без макросов.");
|
|
1816
|
+
let a = Le(await Re(n, "word/document.xml"));
|
|
1817
|
+
if (a.documentElement.localName !== "document" || !a.getElementsByTagNameNS($, "body").length) throw Error("XML документа повреждён или использует неподдерживаемую разновидность DOCX.");
|
|
1289
1818
|
let o = /* @__PURE__ */ new Set(), s = [a];
|
|
1290
1819
|
for (let e of ["word/styles.xml", "word/fontTable.xml"]) {
|
|
1291
|
-
let t = await
|
|
1292
|
-
t && s.push(
|
|
1820
|
+
let t = await Re(n, e);
|
|
1821
|
+
t && s.push(Le(t));
|
|
1293
1822
|
}
|
|
1294
1823
|
for (let e of s) {
|
|
1295
|
-
for (let t of e.getElementsByTagNameNS(
|
|
1824
|
+
for (let t of e.getElementsByTagNameNS($, "rFonts")) for (let e of [
|
|
1296
1825
|
"ascii",
|
|
1297
1826
|
"hAnsi",
|
|
1298
1827
|
"cs",
|
|
1299
1828
|
"eastAsia"
|
|
1300
1829
|
]) {
|
|
1301
|
-
let n = t.getAttributeNS(
|
|
1830
|
+
let n = t.getAttributeNS($, e);
|
|
1302
1831
|
n && o.add(n);
|
|
1303
1832
|
}
|
|
1304
|
-
for (let t of e.getElementsByTagNameNS(
|
|
1305
|
-
let e = t.getAttributeNS(
|
|
1833
|
+
for (let t of e.getElementsByTagNameNS($, "font")) {
|
|
1834
|
+
let e = t.getAttributeNS($, "name");
|
|
1306
1835
|
e && o.add(e);
|
|
1307
1836
|
}
|
|
1308
1837
|
}
|
|
1309
|
-
let c = await
|
|
1310
|
-
if (!
|
|
1311
|
-
return
|
|
1838
|
+
let c = await Re(n, "docProps/app.xml"), l = c ? Number(Le(c).getElementsByTagNameNS("*", "Pages")[0]?.textContent) : 0, { openDocumentForExport: u } = await import("@docx-editor.dev/core/export"), d = u(t.slice());
|
|
1839
|
+
if (!d.ok) throw Error("Не удалось открыть структуру DOCX. Текущий документ сохранён в редакторе.");
|
|
1840
|
+
return d.session.dispose(), {
|
|
1312
1841
|
name: e.name,
|
|
1313
1842
|
original: t,
|
|
1314
1843
|
metadata: {
|
|
1315
|
-
paragraphs: a.getElementsByTagNameNS(
|
|
1316
|
-
tables: a.getElementsByTagNameNS(
|
|
1317
|
-
sections: a.getElementsByTagNameNS(
|
|
1844
|
+
paragraphs: a.getElementsByTagNameNS($, "p").length,
|
|
1845
|
+
tables: a.getElementsByTagNameNS($, "tbl").length,
|
|
1846
|
+
sections: a.getElementsByTagNameNS($, "sectPr").length,
|
|
1318
1847
|
savedPageCount: Number.isSafeInteger(l) && l > 0 ? l : null,
|
|
1319
1848
|
hasHeaders: r.some((e) => /^word\/header[^/]*\.xml$/.test(e)),
|
|
1320
1849
|
hasFooters: r.some((e) => /^word\/footer[^/]*\.xml$/.test(e)),
|
|
1321
|
-
hasReviewContent: r.some((e) => /^word\/comments[^/]*\.xml$/.test(e)) || ["ins", "del"].some((e) => a.getElementsByTagNameNS(
|
|
1850
|
+
hasReviewContent: r.some((e) => /^word\/comments[^/]*\.xml$/.test(e)) || ["ins", "del"].some((e) => a.getElementsByTagNameNS($, e).length > 0),
|
|
1322
1851
|
fonts: [...o].sort()
|
|
1323
1852
|
}
|
|
1324
1853
|
};
|
|
1325
1854
|
}
|
|
1326
|
-
function
|
|
1855
|
+
function Be(e) {
|
|
1327
1856
|
return `${(e.replace(/\.docx$/i, "").replace(/[<>:"/\\|?*\x00-\x1f]/g, "_").trim() || "Документ").replace(/ — редакция$/, "")} — редакция.docx`;
|
|
1328
1857
|
}
|
|
1329
|
-
function
|
|
1330
|
-
let n = URL.createObjectURL(new Blob([e], { type:
|
|
1858
|
+
function Ve(e, t) {
|
|
1859
|
+
let n = URL.createObjectURL(new Blob([e], { type: Pe })), r = document.createElement("a");
|
|
1331
1860
|
r.href = n, r.download = t, document.body.append(r), r.click(), r.remove(), window.setTimeout(() => URL.revokeObjectURL(n), 3e4);
|
|
1332
1861
|
}
|
|
1333
1862
|
//#endregion
|
|
1334
1863
|
//#region src/library/pdf-export.ts
|
|
1335
|
-
async function
|
|
1864
|
+
async function He(e, t, n, r = {}) {
|
|
1336
1865
|
let i = AbortSignal.any([AbortSignal.timeout(95e3), ...r.signal ? [r.signal] : []]);
|
|
1337
1866
|
i.throwIfAborted();
|
|
1338
1867
|
let a = new FormData();
|
|
@@ -1361,13 +1890,13 @@ async function Ee(e, t, n, r = {}) {
|
|
|
1361
1890
|
warnings: (o.headers.get("x-pdf-warnings") ?? "").split(",").filter(Boolean)
|
|
1362
1891
|
};
|
|
1363
1892
|
}
|
|
1364
|
-
function
|
|
1893
|
+
function Ue(e) {
|
|
1365
1894
|
let t = URL.createObjectURL(e.blob), n = document.createElement("a");
|
|
1366
1895
|
n.href = t, n.download = e.filename, document.body.append(n), n.click(), n.remove(), setTimeout(() => URL.revokeObjectURL(t), 6e4);
|
|
1367
1896
|
}
|
|
1368
1897
|
//#endregion
|
|
1369
1898
|
//#region src/library/pdf-profile.ts
|
|
1370
|
-
var
|
|
1899
|
+
var We = {
|
|
1371
1900
|
id: "az-editor-pdf-a0c6eaaeb90716f0",
|
|
1372
1901
|
protocolVersion: 1,
|
|
1373
1902
|
core: "2.27.0",
|
|
@@ -1514,19 +2043,19 @@ var Oe = {
|
|
|
1514
2043
|
};
|
|
1515
2044
|
//#endregion
|
|
1516
2045
|
//#region src/library/hujjat/api.ts
|
|
1517
|
-
function
|
|
1518
|
-
if (!e || !Object.keys(e).length) throw new
|
|
2046
|
+
function Ge(e) {
|
|
2047
|
+
if (!e || !Object.keys(e).length) throw new A("Нет локалей шаблона.");
|
|
1519
2048
|
for (let [t, n] of Object.entries(e)) {
|
|
1520
|
-
if (
|
|
2049
|
+
if (L(t), !n || !Array.isArray(n.blocks) || !n.blocks.length) throw new A(`Нет блоков для ${t}.`);
|
|
1521
2050
|
for (let e of n.blocks) if (e.type === "html") {
|
|
1522
|
-
if (typeof e.props?.html != "string" || !e.props.html.trim()) throw new
|
|
1523
|
-
if (new TextEncoder().encode(e.props.html).length > 1048576) throw new
|
|
2051
|
+
if (typeof e.props?.html != "string" || !e.props.html.trim()) throw new A(`Пустой HTML для ${t}.`);
|
|
2052
|
+
if (new TextEncoder().encode(e.props.html).length > 1048576) throw new A(`HTML для ${t} превышает 1 МБ.`);
|
|
1524
2053
|
}
|
|
1525
2054
|
}
|
|
1526
2055
|
}
|
|
1527
|
-
function
|
|
1528
|
-
if (
|
|
1529
|
-
if (!e.productId || !e.name.trim() || e.name.length > 255) throw new
|
|
2056
|
+
function Ke(e, t) {
|
|
2057
|
+
if (Ge(t), !t.uz) throw new A("Для создания шаблона обязательна локаль uz.");
|
|
2058
|
+
if (!e.productId || !e.name.trim() || e.name.length > 255) throw new A("Укажите продукт и название шаблона до 255 символов.");
|
|
1530
2059
|
return {
|
|
1531
2060
|
product_id: e.productId,
|
|
1532
2061
|
name: e.name,
|
|
@@ -1534,11 +2063,11 @@ function Ae(e, t) {
|
|
|
1534
2063
|
locales: structuredClone(t)
|
|
1535
2064
|
};
|
|
1536
2065
|
}
|
|
1537
|
-
async function
|
|
2066
|
+
async function qe(e) {
|
|
1538
2067
|
let t = AbortSignal.any([AbortSignal.timeout(95e3), ...e.signal ? [e.signal] : []]);
|
|
1539
|
-
t.throwIfAborted(),
|
|
2068
|
+
t.throwIfAborted(), Ge(e.locales);
|
|
1540
2069
|
let n = e.locale ?? "uz";
|
|
1541
|
-
|
|
2070
|
+
L(n);
|
|
1542
2071
|
let r = new Headers(e.headers);
|
|
1543
2072
|
r.set("Content-Type", "application/json"), r.set("Accept", "application/pdf, application/json");
|
|
1544
2073
|
let i = await (e.fetcher ?? fetch)(e.url, {
|
|
@@ -1566,4 +2095,4 @@ async function je(e) {
|
|
|
1566
2095
|
};
|
|
1567
2096
|
}
|
|
1568
2097
|
//#endregion
|
|
1569
|
-
export {
|
|
2098
|
+
export { Ae as AzDocumentEditor, Me as AzHtmlEditor, Pe as DOCX_MIME, O as HUJJAT_LOCALES, k as HUJJAT_MAX_HTML_BYTES, C as HUJJAT_PAGE, A as HujjatCompatibilityError, Ne as MAX_DOCX_BYTES, Ee as analyzeDocxFormatting, Ke as createHujjatTemplatePayload, Ve as downloadDocx, Ue as downloadPdf, Be as exportFilename, we as exportHujjatDocx, Te as importHujjatTemplate, We as pdfRenderProfile, ze as readDocxFile, se as readHujjatHtml, qe as requestHujjatPreview, He as requestPdf, E as resolveHtmlLayout, oe as sanitizeHujjatHtml, P as validateHujjatVariable, ce as withHujjatLocale };
|