@makhmudov.kay/az-editor 0.1.0-beta.3 → 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 +4 -1
- package/dist/az-editor.js +948 -494
- 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/index.d.ts +6 -1
- package/dist/library/layout-profile.d.ts +37 -0
- package/docs/integration.ru.md +23 -8
- 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 U(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 W(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,109 +765,123 @@ async function ce(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
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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,
|
|
627
803
|
list: {
|
|
628
|
-
id:
|
|
629
|
-
level: Math.min(
|
|
804
|
+
id: c,
|
|
805
|
+
level: Math.min(u, 8),
|
|
630
806
|
tag: n === "bullet" ? "ul" : "ol"
|
|
631
807
|
}
|
|
632
808
|
};
|
|
633
809
|
}
|
|
634
810
|
return {
|
|
635
|
-
html:
|
|
636
|
-
continuation:
|
|
811
|
+
html: j,
|
|
812
|
+
continuation: U(r, "pStyle") === "AzHujjatListContinuation"
|
|
637
813
|
};
|
|
638
814
|
}
|
|
639
|
-
function
|
|
640
|
-
|
|
641
|
-
let n =
|
|
642
|
-
|
|
643
|
-
let r =
|
|
644
|
-
o.forEach((e,
|
|
645
|
-
let
|
|
646
|
-
Number(
|
|
647
|
-
for (let
|
|
648
|
-
let e =
|
|
649
|
-
if (
|
|
650
|
-
if (h &&
|
|
651
|
-
let e = s.get(
|
|
652
|
-
if (e.rowSpan++, e.rowSpan > 100) throw new
|
|
653
|
-
|
|
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;
|
|
654
830
|
continue;
|
|
655
831
|
}
|
|
656
|
-
let g = {}, _ =
|
|
657
|
-
|
|
658
|
-
let v = i.slice(
|
|
659
|
-
(a || !g.width) && v.length ===
|
|
660
|
-
let y =
|
|
661
|
-
/^[\da-f]{6}$/i.test(y) && (g["background-color"] = "#" + y),
|
|
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"));
|
|
662
838
|
for (let t of [
|
|
663
839
|
"top",
|
|
664
840
|
"right",
|
|
665
841
|
"bottom",
|
|
666
842
|
"left"
|
|
667
843
|
]) {
|
|
668
|
-
let i =
|
|
669
|
-
|
|
670
|
-
let
|
|
671
|
-
|
|
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")));
|
|
672
848
|
}
|
|
673
849
|
let b = {
|
|
674
|
-
element:
|
|
850
|
+
element: u,
|
|
675
851
|
rowSpan: 1,
|
|
676
|
-
span:
|
|
677
|
-
html:
|
|
852
|
+
span: p,
|
|
853
|
+
html: P(u, t + 1),
|
|
678
854
|
css: g
|
|
679
855
|
};
|
|
680
|
-
for (let e =
|
|
681
|
-
h &&
|
|
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;
|
|
682
858
|
}
|
|
683
|
-
for (let e of s.keys()) e >=
|
|
684
|
-
|
|
859
|
+
for (let e of s.keys()) e >= d && s.delete(e);
|
|
860
|
+
u.push(f);
|
|
685
861
|
});
|
|
686
|
-
let
|
|
687
|
-
width:
|
|
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%",
|
|
688
864
|
"border-collapse": "collapse"
|
|
689
|
-
};
|
|
690
|
-
return a && (
|
|
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>`;
|
|
691
867
|
}
|
|
692
|
-
function
|
|
693
|
-
|
|
868
|
+
function P(e, t) {
|
|
869
|
+
O(t);
|
|
694
870
|
let n = "", r, i = () => {
|
|
695
871
|
r && (n += `</${r.tag}>`), r = void 0;
|
|
696
872
|
};
|
|
697
|
-
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.");
|
|
698
874
|
else if (a.localName === "p") {
|
|
699
|
-
let e =
|
|
700
|
-
e.list ? ((r?.id !== e.list.id || r.tag !== e.list.tag) && (i(), r = e.list, r.tag === "ol" &&
|
|
701
|
-
} else
|
|
702
|
-
else if (a.localName === "sectPr") {
|
|
703
|
-
let e = L(a, "pgSz"), t = L(a, "pgMar");
|
|
704
|
-
(R(e, "orient") === "landscape" || R(e, "w") && Math.abs(Number(R(e, "w")) - 11906) > 2 || R(t, "bottom") && Math.abs(Number(R(t, "bottom")) - 1984) > 2) && w(c, "page-normalized", "Размеры и поля Word заменяются настройками Hujjat: A4, 15/20/35/20 мм.");
|
|
705
|
-
} 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" || ([
|
|
706
878
|
"sdt",
|
|
707
879
|
"customXml",
|
|
708
880
|
"ins",
|
|
709
881
|
"del",
|
|
710
882
|
"moveFrom",
|
|
711
883
|
"moveTo"
|
|
712
|
-
].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))) : [
|
|
713
885
|
"tblPr",
|
|
714
886
|
"tblGrid",
|
|
715
887
|
"tcPr",
|
|
@@ -717,18 +889,19 @@ async function ce(e) {
|
|
|
717
889
|
"bookmarkStart",
|
|
718
890
|
"bookmarkEnd",
|
|
719
891
|
"proofErr"
|
|
720
|
-
].includes(a.localName) || (i(),
|
|
892
|
+
].includes(a.localName) || (i(), m("unsupported-block", `Блок Word ${a.localName} не поддерживается HTML-адаптером.`)));
|
|
721
893
|
return i(), n;
|
|
722
894
|
}
|
|
723
895
|
return {
|
|
724
|
-
html:
|
|
725
|
-
warnings:
|
|
896
|
+
html: P(c, 0) || "<p><br></p>",
|
|
897
|
+
warnings: l,
|
|
898
|
+
layout: u
|
|
726
899
|
};
|
|
727
900
|
}
|
|
728
901
|
//#endregion
|
|
729
902
|
//#region src/library/hujjat/table-grid.ts
|
|
730
|
-
function
|
|
731
|
-
let i = Array.from({ length: e }), a = () =>
|
|
903
|
+
function ye(e, t, n, r) {
|
|
904
|
+
let i = Array.from({ length: e }), a = () => M(r, "table-width-normalized", "Противоречивые ширины ячеек приведены к общей сетке таблицы.");
|
|
732
905
|
for (let e of [...n].sort((e, t) => e.span - t.span)) {
|
|
733
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);
|
|
734
907
|
if (!n.length) {
|
|
@@ -760,10 +933,7 @@ function le(e, t, n, r) {
|
|
|
760
933
|
}
|
|
761
934
|
//#endregion
|
|
762
935
|
//#region src/library/hujjat/html-to-docx.ts
|
|
763
|
-
var
|
|
764
|
-
width: 9638,
|
|
765
|
-
cell: !1
|
|
766
|
-
}, de = /^(font-|color$|text-align$|text-indent$|text-transform$|line-height$|letter-spacing$|white-space$|text-decoration$|vertical-align$)/, G = new Set("p div h1 h2 h3 h4 h5 h6 ul ol li table hr".split(" ")), fe = {
|
|
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 = {
|
|
767
937
|
black: "000000",
|
|
768
938
|
white: "FFFFFF",
|
|
769
939
|
red: "FF0000",
|
|
@@ -782,14 +952,14 @@ var ue = {
|
|
|
782
952
|
teal: "008080",
|
|
783
953
|
aqua: "00FFFF"
|
|
784
954
|
};
|
|
785
|
-
function
|
|
955
|
+
function J(e) {
|
|
786
956
|
if (!e) return;
|
|
787
957
|
if (/^#[\da-f]{6}$/i.test(e)) return e.slice(1);
|
|
788
958
|
if (/^#[\da-f]{3}$/i.test(e)) return e.slice(1).split("").map((e) => e + e).join("");
|
|
789
959
|
let t = e.match(/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
|
|
790
|
-
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()];
|
|
791
961
|
}
|
|
792
|
-
function
|
|
962
|
+
function Y(e) {
|
|
793
963
|
if (e === "0") return 0;
|
|
794
964
|
let t = e?.match(/^(-?\d*\.?\d+)(pt|px|in|cm|mm|pc)$/i);
|
|
795
965
|
return t ? Number(t[1]) * {
|
|
@@ -801,11 +971,11 @@ function q(e) {
|
|
|
801
971
|
pc: 12
|
|
802
972
|
}[t[2].toLowerCase()] : void 0;
|
|
803
973
|
}
|
|
804
|
-
var
|
|
805
|
-
let t =
|
|
974
|
+
var X = (e) => {
|
|
975
|
+
let t = Y(e);
|
|
806
976
|
return t === void 0 ? void 0 : Math.round(t * 20);
|
|
807
977
|
};
|
|
808
|
-
function
|
|
978
|
+
function Z(e, t) {
|
|
809
979
|
let n = { ...t }, r = e.style;
|
|
810
980
|
for (let e of Array.from(r)) n[e] = r.getPropertyValue(e).trim();
|
|
811
981
|
for (let e of ["margin", "padding"]) for (let t of [
|
|
@@ -824,80 +994,115 @@ function Y(e, t) {
|
|
|
824
994
|
h3: "12pt"
|
|
825
995
|
}[i] ?? "12pt"), r.fontWeight || (n["font-weight"] = "bold")), n;
|
|
826
996
|
}
|
|
827
|
-
var
|
|
828
|
-
async function
|
|
829
|
-
let
|
|
830
|
-
|
|
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() {
|
|
831
1013
|
let e = !0;
|
|
832
|
-
for (let t of
|
|
1014
|
+
for (let t of l) t.data = t.data.replace(/[\t\r\n\f ]+/g, " ").split("").filter((t) => {
|
|
833
1015
|
if (t === " ") {
|
|
834
1016
|
if (e) return !1;
|
|
835
1017
|
e = !0;
|
|
836
1018
|
} else e = !1;
|
|
837
1019
|
return !0;
|
|
838
1020
|
}).join("");
|
|
839
|
-
for (let e =
|
|
840
|
-
|
|
1021
|
+
for (let e = l.length - 1; e >= 0; e--) if (l[e].data) {
|
|
1022
|
+
l[e].data = l[e].data.replace(/ $/, "");
|
|
841
1023
|
break;
|
|
842
1024
|
}
|
|
843
|
-
|
|
1025
|
+
l = [];
|
|
844
1026
|
}
|
|
845
|
-
function
|
|
1027
|
+
function d(e, n = !1) {
|
|
846
1028
|
if (e.nodeType === 3) {
|
|
847
|
-
n ||
|
|
1029
|
+
n || l.push(e);
|
|
848
1030
|
return;
|
|
849
1031
|
}
|
|
850
|
-
let r = e instanceof Element ? e : null, i = r && (
|
|
1032
|
+
let r = e instanceof Element ? e : null, i = r && (xe.has(r.localName) || [
|
|
851
1033
|
"br",
|
|
852
1034
|
"td",
|
|
853
1035
|
"th",
|
|
854
1036
|
"tr"
|
|
855
|
-
].includes(r.localName)),
|
|
856
|
-
(i ||
|
|
857
|
-
for (let t of e.childNodes)
|
|
858
|
-
(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();
|
|
859
1041
|
}
|
|
860
|
-
|
|
861
|
-
let
|
|
1042
|
+
d(i), u();
|
|
1043
|
+
let f = {
|
|
862
1044
|
"font-family": "freeserif",
|
|
863
1045
|
"font-size": "12pt",
|
|
864
1046
|
color: "#111111"
|
|
865
1047
|
};
|
|
866
|
-
function
|
|
867
|
-
let t = `<w:rFonts w:ascii="${
|
|
868
|
-
return n !== void 0 && (t += `<w:sz w:val="${Math.round(n * 2)}"/>`), e["font-weight"] && (t += `<w:b w:val="${e["font-weight"] === "bold" || Number(e["font-weight"]) >= 600 ? "1" : "0"}"/>`), e["font-style"] && (t += `<w:i w:val="${e["font-style"] === "italic" ? "1" : "0"}"/>`), e["text-decoration"] && (t += `<w:u w:val="${e["text-decoration"].includes("underline") ? "single" : "none"}"/><w:strike w:val="${e["text-decoration"].includes("line-through") ? "1" : "0"}"/>`),
|
|
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;
|
|
869
1051
|
}
|
|
870
|
-
function
|
|
1052
|
+
function h(e, t) {
|
|
871
1053
|
let n = "";
|
|
872
|
-
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)));
|
|
873
1055
|
return n;
|
|
874
1056
|
}
|
|
875
|
-
function
|
|
876
|
-
let
|
|
1057
|
+
function g(e, i, a, o = r) {
|
|
1058
|
+
let s = "", c = i["text-align"];
|
|
877
1059
|
[
|
|
878
1060
|
"left",
|
|
879
1061
|
"right",
|
|
880
1062
|
"center",
|
|
881
1063
|
"justify"
|
|
882
|
-
].includes(
|
|
883
|
-
let
|
|
884
|
-
if (
|
|
885
|
-
let e = parseFloat(
|
|
886
|
-
e < 1 &&
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
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 = "";
|
|
890
1077
|
for (let [e, t] of [
|
|
891
1078
|
["margin-left", "left"],
|
|
892
1079
|
["margin-right", "right"],
|
|
893
1080
|
["text-indent", "firstLine"]
|
|
894
1081
|
]) {
|
|
895
|
-
let r =
|
|
896
|
-
|
|
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}"`);
|
|
897
1084
|
}
|
|
898
|
-
|
|
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>" : "");
|
|
899
1104
|
}
|
|
900
|
-
function
|
|
1105
|
+
function _(e, t) {
|
|
901
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;
|
|
902
1107
|
return !r && !i ? "" : `<w:${t} w:val="${{
|
|
903
1108
|
solid: "single",
|
|
@@ -905,12 +1110,14 @@ async function pe(e, t) {
|
|
|
905
1110
|
dotted: "dotted",
|
|
906
1111
|
double: "double",
|
|
907
1112
|
none: "nil"
|
|
908
|
-
}[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"}"/>`;
|
|
909
1114
|
}
|
|
910
|
-
function
|
|
911
|
-
let i = Array.from(e.querySelectorAll("tr")).filter((t) => t.closest("table") === e), a = /* @__PURE__ */ new Map(), o = 1, s = [], c = n.width?.endsWith("%") ? parseFloat(n.width) : void 0, l = Math.max(1, Math.round(
|
|
912
|
-
|
|
913
|
-
|
|
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) => {
|
|
914
1121
|
let r = 0, i = [];
|
|
915
1122
|
function c() {
|
|
916
1123
|
for (; a.has(r);) {
|
|
@@ -920,21 +1127,21 @@ async function pe(e, t) {
|
|
|
920
1127
|
span: e.span,
|
|
921
1128
|
rowSpan: 0,
|
|
922
1129
|
css: {}
|
|
923
|
-
}), --e.remaining === 0 && a.delete(r), r += e.span,
|
|
1130
|
+
}), --e.remaining === 0 && a.delete(r), r += e.span, p(r);
|
|
924
1131
|
}
|
|
925
1132
|
}
|
|
926
1133
|
for (let o of Array.from(t.children).filter((e) => e.localName === "td" || e.localName === "th")) {
|
|
927
1134
|
c();
|
|
928
|
-
let t = Number(o.getAttribute("colspan") || 1),
|
|
929
|
-
|
|
930
|
-
let
|
|
931
|
-
for (;
|
|
1135
|
+
let t = Number(o.getAttribute("colspan") || 1), l = Number(o.getAttribute("rowspan") || 1);
|
|
1136
|
+
p(r + t);
|
|
1137
|
+
let u = [], d = o.parentElement;
|
|
1138
|
+
for (; d && d !== e;) u.unshift(d), d = d.parentElement;
|
|
932
1139
|
let m = (e) => ({
|
|
933
|
-
...
|
|
1140
|
+
...Q(e),
|
|
934
1141
|
...e["background-color"] ? { "background-color": e["background-color"] } : {}
|
|
935
|
-
}), h =
|
|
1142
|
+
}), h = Z(o, m(u.reduce((e, t) => Z(t, m(e)), n)));
|
|
936
1143
|
o.localName === "th" && (h["font-weight"] = "bold");
|
|
937
|
-
let g =
|
|
1144
|
+
let g = X(h.width) ?? (h.width?.endsWith("%") ? parseFloat(h.width) * f / 100 : void 0);
|
|
938
1145
|
g !== void 0 && Number.isFinite(g) && g > 0 && s.push({
|
|
939
1146
|
column: r,
|
|
940
1147
|
span: t,
|
|
@@ -943,10 +1150,10 @@ async function pe(e, t) {
|
|
|
943
1150
|
element: o,
|
|
944
1151
|
column: r,
|
|
945
1152
|
span: t,
|
|
946
|
-
rowSpan:
|
|
1153
|
+
rowSpan: l,
|
|
947
1154
|
css: h
|
|
948
|
-
}),
|
|
949
|
-
remaining:
|
|
1155
|
+
}), l > 1 && a.set(r, {
|
|
1156
|
+
remaining: l - 1,
|
|
950
1157
|
span: t
|
|
951
1158
|
}), r += t;
|
|
952
1159
|
}
|
|
@@ -962,10 +1169,10 @@ async function pe(e, t) {
|
|
|
962
1169
|
c();
|
|
963
1170
|
}
|
|
964
1171
|
return o = Math.max(o, r), i;
|
|
965
|
-
}),
|
|
966
|
-
let a =
|
|
967
|
-
if (n > 1 && (o += `<w:gridSpan w:val="${n}"/>`), r > 1 && (o += "<w:vMerge w:val=\"restart\"/>"), !e) return `<w:tc><w:tcPr>${o}${r === 0 ? "<w:vMerge/>" : ""}</w:tcPr>${
|
|
968
|
-
let s =
|
|
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"]);
|
|
969
1176
|
s && (o += `<w:shd w:fill="${s}"/>`), [
|
|
970
1177
|
"top",
|
|
971
1178
|
"middle",
|
|
@@ -976,294 +1183,534 @@ async function pe(e, t) {
|
|
|
976
1183
|
"left",
|
|
977
1184
|
"bottom",
|
|
978
1185
|
"right"
|
|
979
|
-
], l = c.map((t) =>
|
|
1186
|
+
], l = c.map((t) => _(e, t)).join("");
|
|
980
1187
|
l && (o += `<w:tcBorders>${l}</w:tcBorders>`);
|
|
981
|
-
let u = c.map((e) =>
|
|
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("");
|
|
982
1189
|
u && (o += `<w:tcMar>${u}</w:tcMar>`);
|
|
983
|
-
let d = Math.max(1, a - Math.max(0,
|
|
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, {
|
|
984
1191
|
width: d,
|
|
985
1192
|
cell: !0
|
|
986
1193
|
});
|
|
987
|
-
return (!
|
|
988
|
-
}).join("") || `<w:tc>${
|
|
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 = [
|
|
989
1196
|
"top",
|
|
990
1197
|
"left",
|
|
991
1198
|
"bottom",
|
|
992
1199
|
"right"
|
|
993
|
-
].map((t) =>
|
|
994
|
-
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>`;
|
|
995
1202
|
}
|
|
996
|
-
function
|
|
997
|
-
let
|
|
998
|
-
c
|
|
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 = [];
|
|
999
1210
|
};
|
|
1000
|
-
for (let
|
|
1001
|
-
if (!(
|
|
1002
|
-
|
|
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);
|
|
1003
1214
|
continue;
|
|
1004
1215
|
}
|
|
1005
|
-
|
|
1006
|
-
let
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
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,
|
|
1017
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)
|
|
1018
1239
|
};
|
|
1019
|
-
|
|
1240
|
+
l += y(r.childNodes, a, i, o) || g([], a, i, o);
|
|
1020
1241
|
}
|
|
1021
|
-
} else
|
|
1242
|
+
} else r.localName === "div" && Array.from(r.children).some((e) => xe.has(e.localName)) ? (f["page-break-before"] === "always" && (l += g([], {
|
|
1022
1243
|
"page-break-before": "always",
|
|
1023
1244
|
"margin-bottom": "0pt"
|
|
1024
|
-
})),
|
|
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([], {
|
|
1025
1252
|
"page-break-before": "always",
|
|
1026
1253
|
"margin-bottom": "0pt"
|
|
1027
|
-
}))) :
|
|
1254
|
+
}))) : r.localName === "hr" ? (M(t, "rule-normalized", "Разделитель HTML преобразован в строку."), l += g([document.createTextNode("────────────────")], f, void 0, c)) : l += g(r.childNodes, f, i, h);
|
|
1028
1255
|
}
|
|
1029
|
-
return
|
|
1256
|
+
return m(f.length - 1), l;
|
|
1030
1257
|
}
|
|
1031
|
-
let
|
|
1032
|
-
if (new TextEncoder().encode(
|
|
1033
|
-
let
|
|
1034
|
-
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)) {
|
|
1035
1262
|
let r = e.style.getPropertyValue(n), i = ["td", "th"].includes(e.localName);
|
|
1036
|
-
|
|
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
|
+
});
|
|
1037
1277
|
}
|
|
1038
|
-
let
|
|
1039
|
-
|
|
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({
|
|
1040
1282
|
type: "arraybuffer",
|
|
1041
1283
|
compression: "DEFLATE"
|
|
1042
1284
|
}));
|
|
1043
1285
|
}
|
|
1044
1286
|
//#endregion
|
|
1045
1287
|
//#region src/library/hujjat/docx.ts
|
|
1046
|
-
async function
|
|
1047
|
-
let n = await
|
|
1048
|
-
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;
|
|
1049
1291
|
}
|
|
1050
|
-
async function
|
|
1051
|
-
let r =
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
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
|
+
}
|
|
1055
1412
|
};
|
|
1056
1413
|
}
|
|
1057
1414
|
//#endregion
|
|
1058
1415
|
//#region src/library/AzDocumentEditor.tsx
|
|
1059
|
-
var
|
|
1060
|
-
function
|
|
1061
|
-
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
|
+
]);
|
|
1062
1439
|
return n(() => {
|
|
1063
|
-
|
|
1064
|
-
pages:
|
|
1065
|
-
loading:
|
|
1066
|
-
error:
|
|
1440
|
+
r.current?.({
|
|
1441
|
+
pages: s,
|
|
1442
|
+
loading: c,
|
|
1443
|
+
error: l,
|
|
1444
|
+
fonts: f
|
|
1067
1445
|
});
|
|
1068
1446
|
}, [
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1447
|
+
s,
|
|
1448
|
+
c,
|
|
1449
|
+
l,
|
|
1450
|
+
f
|
|
1073
1451
|
]), null;
|
|
1074
1452
|
}
|
|
1075
|
-
var
|
|
1076
|
-
let
|
|
1077
|
-
|
|
1078
|
-
|
|
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\"]");
|
|
1079
1485
|
t?.click(), t?.focus(), e();
|
|
1080
1486
|
}
|
|
1081
|
-
async function
|
|
1082
|
-
let t =
|
|
1083
|
-
if (!t || !
|
|
1084
|
-
|
|
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();
|
|
1085
1491
|
let n = new AbortController();
|
|
1086
|
-
|
|
1492
|
+
m.current = n, y("");
|
|
1087
1493
|
try {
|
|
1088
|
-
await
|
|
1494
|
+
await S(t, p.current, e.title ?? "Документ.docx", n.signal);
|
|
1089
1495
|
} catch (e) {
|
|
1090
|
-
!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.");
|
|
1091
1497
|
}
|
|
1092
1498
|
}
|
|
1093
|
-
return n(() => () =>
|
|
1499
|
+
return n(() => () => m.current?.abort(), []), n(() => {
|
|
1094
1500
|
let t = (t) => {
|
|
1095
|
-
if (t.defaultPrevented || !(t.ctrlKey || t.metaKey) || t.altKey || t.shiftKey || !
|
|
1096
|
-
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;
|
|
1097
1503
|
t.preventDefault(), t.stopImmediatePropagation(), e.actionsDisabled || n?.();
|
|
1098
1504
|
};
|
|
1099
1505
|
return window.addEventListener("keydown", t, !0), () => window.removeEventListener("keydown", t, !0);
|
|
1100
1506
|
}), r(t, () => ({
|
|
1101
1507
|
async save() {
|
|
1102
|
-
let e = await
|
|
1103
|
-
if (!
|
|
1104
|
-
return e;
|
|
1508
|
+
let e = O.current, t = await u.current?.save();
|
|
1509
|
+
if (!t) throw Error("Документ ещё не готов к сохранению.");
|
|
1510
|
+
return M(t, e), t;
|
|
1105
1511
|
},
|
|
1106
1512
|
async exportHujjat(e) {
|
|
1107
|
-
let t = await
|
|
1108
|
-
if (!t) throw new
|
|
1109
|
-
return
|
|
1513
|
+
let t = await u.current?.save();
|
|
1514
|
+
if (!t) throw new A("Документ ещё не готов к экспорту.");
|
|
1515
|
+
return we(t, e);
|
|
1110
1516
|
},
|
|
1111
1517
|
insertVariable(e) {
|
|
1112
|
-
if (!
|
|
1113
|
-
let t =
|
|
1518
|
+
if (!P(e)) throw new A("Некорректный ключ переменной. Используйте client.name, ASCII, до 100 символов.");
|
|
1519
|
+
let t = u.current?.exec({
|
|
1114
1520
|
type: "pasteWithoutFormatting",
|
|
1115
1521
|
text: `{${e}}`
|
|
1116
1522
|
});
|
|
1117
|
-
if (!t?.ok) throw new
|
|
1118
|
-
|
|
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();
|
|
1119
1546
|
},
|
|
1120
1547
|
focus() {
|
|
1121
|
-
|
|
1548
|
+
u.current?.focus();
|
|
1122
1549
|
},
|
|
1123
|
-
print:
|
|
1124
|
-
})), /* @__PURE__ */
|
|
1550
|
+
print: I
|
|
1551
|
+
})), /* @__PURE__ */ g("div", {
|
|
1125
1552
|
className: ["az-document-editor", e.className].filter(Boolean).join(" "),
|
|
1126
1553
|
style: e.style,
|
|
1127
|
-
ref:
|
|
1128
|
-
children: [
|
|
1554
|
+
ref: p,
|
|
1555
|
+
children: [v && /* @__PURE__ */ h("div", {
|
|
1129
1556
|
role: "alert",
|
|
1130
1557
|
className: "az-print-error",
|
|
1131
|
-
children:
|
|
1132
|
-
}), /* @__PURE__ */
|
|
1133
|
-
ref:
|
|
1558
|
+
children: v
|
|
1559
|
+
}), /* @__PURE__ */ h(l, {
|
|
1560
|
+
ref: u,
|
|
1134
1561
|
document: e.document ?? "blank",
|
|
1135
1562
|
title: e.title ?? "Документ.docx",
|
|
1136
|
-
fonts:
|
|
1563
|
+
fonts: T.fonts,
|
|
1137
1564
|
locale: e.locale ?? "ru-RU",
|
|
1138
|
-
i18n: e.i18n ??
|
|
1565
|
+
i18n: e.i18n ?? _,
|
|
1139
1566
|
mode: e.mode ?? "edit",
|
|
1140
1567
|
colorMode: e.colorMode ?? "light",
|
|
1141
1568
|
zoom: e.zoom,
|
|
1142
1569
|
zoomMode: e.zoomMode,
|
|
1143
|
-
chrome:
|
|
1144
|
-
rulers:
|
|
1145
|
-
navigation:
|
|
1146
|
-
contextMenu:
|
|
1570
|
+
chrome: N("chrome"),
|
|
1571
|
+
rulers: N("rulers"),
|
|
1572
|
+
navigation: N("navigation"),
|
|
1573
|
+
contextMenu: N("contextMenu"),
|
|
1147
1574
|
renderTitleBarLeft: e.renderTitleBarLeft,
|
|
1148
1575
|
renderTitleBarRight: e.renderTitleBarRight,
|
|
1149
1576
|
onChange: (t) => {
|
|
1150
|
-
t.source || e.onChange?.();
|
|
1577
|
+
t.source || (++O.current, D.current.onDiagnostics?.([]), e.onChange?.());
|
|
1151
1578
|
},
|
|
1152
1579
|
onSave: e.onSave,
|
|
1153
1580
|
onOpen: e.onOpen,
|
|
1154
|
-
onFontError: (
|
|
1155
|
-
|
|
1581
|
+
onFontError: (e) => {
|
|
1582
|
+
j.current === T && k.current && (T.fail(e.code), D.current.onFontError?.(`Не удалось загрузить шрифт (${e.code}). Переносы могут отличаться от Word.`));
|
|
1583
|
+
},
|
|
1584
|
+
menu: N("menu") && {
|
|
1156
1585
|
reportIssue: !1,
|
|
1157
|
-
onOpen:
|
|
1158
|
-
onSave:
|
|
1159
|
-
children: /* @__PURE__ */
|
|
1586
|
+
onOpen: Oe,
|
|
1587
|
+
onSave: Oe,
|
|
1588
|
+
children: /* @__PURE__ */ g(l.Menu.File, {
|
|
1160
1589
|
preset: !1,
|
|
1161
1590
|
children: [
|
|
1162
|
-
e.fileActions?.map((t) => /* @__PURE__ */
|
|
1163
|
-
onSelect: () =>
|
|
1591
|
+
e.fileActions?.map((t) => /* @__PURE__ */ h(l.Menu.Row, {
|
|
1592
|
+
onSelect: () => F(t.onSelect),
|
|
1164
1593
|
disabled: e.actionsDisabled || t.disabled,
|
|
1165
1594
|
children: t.label
|
|
1166
1595
|
}, t.id)),
|
|
1167
|
-
e.onOpen && /* @__PURE__ */
|
|
1168
|
-
onSelect: () =>
|
|
1596
|
+
e.onOpen && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1597
|
+
onSelect: () => F(e.onOpen),
|
|
1169
1598
|
disabled: e.actionsDisabled,
|
|
1170
1599
|
shortcut: "Ctrl+O",
|
|
1171
|
-
children: e.labels?.open ?? e.i18n?.toolbar?.open ??
|
|
1600
|
+
children: e.labels?.open ?? e.i18n?.toolbar?.open ?? _.toolbar?.open
|
|
1172
1601
|
}),
|
|
1173
|
-
e.onSave && /* @__PURE__ */
|
|
1174
|
-
onSelect: () =>
|
|
1602
|
+
e.onSave && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1603
|
+
onSelect: () => F(e.onSave),
|
|
1175
1604
|
disabled: e.actionsDisabled,
|
|
1176
1605
|
shortcut: "Ctrl+S",
|
|
1177
|
-
children: e.labels?.save ?? e.i18n?.toolbar?.save ??
|
|
1606
|
+
children: e.labels?.save ?? e.i18n?.toolbar?.save ?? _.toolbar?.save
|
|
1178
1607
|
}),
|
|
1179
|
-
e.onExportPdf && /* @__PURE__ */
|
|
1180
|
-
onSelect: () =>
|
|
1608
|
+
e.onExportPdf && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1609
|
+
onSelect: () => F(e.onExportPdf),
|
|
1181
1610
|
disabled: e.actionsDisabled,
|
|
1182
1611
|
children: e.labels?.exportPdf ?? "Скачать PDF"
|
|
1183
1612
|
}),
|
|
1184
|
-
|
|
1185
|
-
onSelect: () =>
|
|
1613
|
+
N("print") && /* @__PURE__ */ h(l.Menu.Row, {
|
|
1614
|
+
onSelect: () => F(() => void I()),
|
|
1186
1615
|
disabled: e.actionsDisabled,
|
|
1187
1616
|
shortcut: "Ctrl+P",
|
|
1188
1617
|
children: e.labels?.print ?? "Распечатать…"
|
|
1189
1618
|
}),
|
|
1190
|
-
/* @__PURE__ */
|
|
1619
|
+
/* @__PURE__ */ h(l.Menu.PageSetup, {})
|
|
1191
1620
|
]
|
|
1192
1621
|
})
|
|
1193
1622
|
},
|
|
1194
|
-
children: /* @__PURE__ */
|
|
1623
|
+
children: /* @__PURE__ */ h(ke, {
|
|
1624
|
+
onStatusChange: e.onStatusChange,
|
|
1625
|
+
fonts: E
|
|
1626
|
+
})
|
|
1195
1627
|
})]
|
|
1196
1628
|
});
|
|
1197
1629
|
});
|
|
1198
1630
|
//#endregion
|
|
1199
1631
|
//#region src/library/AzHtmlEditor.tsx
|
|
1200
|
-
function
|
|
1632
|
+
function je(...e) {
|
|
1201
1633
|
let t = /* @__PURE__ */ new Map();
|
|
1202
1634
|
for (let n of e.flat()) t.set(JSON.stringify(n), n);
|
|
1203
1635
|
return [...t.values()];
|
|
1204
1636
|
}
|
|
1205
|
-
var
|
|
1206
|
-
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({
|
|
1207
1645
|
phase: "loading",
|
|
1208
1646
|
dirty: !1,
|
|
1209
1647
|
pages: 0,
|
|
1210
1648
|
error: null,
|
|
1211
1649
|
warnings: []
|
|
1212
|
-
}),
|
|
1650
|
+
}), S = o(b), C = o(null), w = o(null), T = o(!1), E = o(0), D = o(0), O = o(e);
|
|
1213
1651
|
i(() => {
|
|
1214
1652
|
O.current = e;
|
|
1215
1653
|
});
|
|
1216
1654
|
let k = t((e) => {
|
|
1217
|
-
|
|
1218
|
-
...
|
|
1655
|
+
T.current && (S.current = {
|
|
1656
|
+
...S.current,
|
|
1219
1657
|
...e
|
|
1220
|
-
},
|
|
1221
|
-
}, []),
|
|
1658
|
+
}, x(S.current), O.current.onStatusChange?.(S.current));
|
|
1659
|
+
}, []), j = t(async (e = !1) => {
|
|
1222
1660
|
let t = ++E.current;
|
|
1223
1661
|
k({
|
|
1224
1662
|
phase: "loading",
|
|
1225
1663
|
error: null
|
|
1226
1664
|
});
|
|
1227
1665
|
try {
|
|
1228
|
-
let n = await
|
|
1666
|
+
let n = await Te({ uz: { blocks: [{
|
|
1229
1667
|
type: "html",
|
|
1230
|
-
props: { html:
|
|
1231
|
-
}] } }, "uz", {
|
|
1232
|
-
|
|
1233
|
-
|
|
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 });
|
|
1234
1675
|
} catch (e) {
|
|
1235
|
-
if (!
|
|
1236
|
-
let n = e instanceof
|
|
1676
|
+
if (!T.current || t !== E.current) return;
|
|
1677
|
+
let n = e instanceof A ? e.warnings : [];
|
|
1237
1678
|
k({
|
|
1238
1679
|
phase: n.some((e) => e.severity === "loss") ? "blocked" : "error",
|
|
1239
1680
|
warnings: n,
|
|
1240
1681
|
error: e instanceof Error ? e.message : String(e)
|
|
1241
1682
|
});
|
|
1242
1683
|
}
|
|
1243
|
-
}, [
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
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";
|
|
1249
1694
|
k({
|
|
1250
1695
|
phase: t,
|
|
1251
1696
|
pages: e.pages,
|
|
1252
|
-
error: e.error
|
|
1697
|
+
error: e.error,
|
|
1698
|
+
fonts: e.fonts
|
|
1253
1699
|
});
|
|
1254
|
-
}, [k]),
|
|
1255
|
-
|
|
1256
|
-
}, [k]),
|
|
1257
|
-
|
|
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" });
|
|
1258
1704
|
}, [k]);
|
|
1259
|
-
return r(
|
|
1705
|
+
return r(a, () => ({
|
|
1260
1706
|
async exportHtml(e = {}) {
|
|
1261
|
-
if (!
|
|
1262
|
-
let t =
|
|
1263
|
-
if (!
|
|
1264
|
-
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,
|
|
1265
1711
|
variables: [...t.variables],
|
|
1266
1712
|
warnings: [...t.warnings],
|
|
1713
|
+
layout: t.layout ? structuredClone(t.layout) : void 0,
|
|
1267
1714
|
changed: !1
|
|
1268
1715
|
};
|
|
1269
1716
|
let n = E.current, r = D.current;
|
|
@@ -1272,71 +1719,78 @@ var be = e(function(e, s) {
|
|
|
1272
1719
|
error: null
|
|
1273
1720
|
});
|
|
1274
1721
|
try {
|
|
1275
|
-
let i = await
|
|
1722
|
+
let i = await C.current.exportHujjat({
|
|
1276
1723
|
locale: "uz",
|
|
1277
|
-
allowLossy: !0
|
|
1724
|
+
allowLossy: !0,
|
|
1725
|
+
layout: _
|
|
1278
1726
|
});
|
|
1279
|
-
if (!
|
|
1280
|
-
let a =
|
|
1281
|
-
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), {
|
|
1282
1730
|
html: i.html,
|
|
1283
1731
|
variables: i.variables,
|
|
1284
1732
|
warnings: a,
|
|
1733
|
+
layout: i.layout,
|
|
1285
1734
|
changed: !0
|
|
1286
1735
|
};
|
|
1287
1736
|
} finally {
|
|
1288
|
-
|
|
1737
|
+
F(n);
|
|
1289
1738
|
}
|
|
1290
1739
|
},
|
|
1291
1740
|
async acceptImportLoss() {
|
|
1292
|
-
if (!
|
|
1293
|
-
await
|
|
1741
|
+
if (!T.current || S.current.phase !== "blocked") throw new A("Нет ожидающего решения об импорте.");
|
|
1742
|
+
await j(!0);
|
|
1294
1743
|
},
|
|
1295
1744
|
insertVariable(e) {
|
|
1296
|
-
if (!
|
|
1297
|
-
|
|
1745
|
+
if (!T.current || S.current.phase !== "ready" || O.current.mode === "view" || !C.current) throw new A("Редактор недоступен для изменения.");
|
|
1746
|
+
C.current.insertVariable(e);
|
|
1298
1747
|
},
|
|
1299
1748
|
focus() {
|
|
1300
|
-
|
|
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);
|
|
1301
1754
|
}
|
|
1302
1755
|
}), [
|
|
1303
|
-
|
|
1304
|
-
|
|
1756
|
+
m,
|
|
1757
|
+
_,
|
|
1758
|
+
j,
|
|
1305
1759
|
k,
|
|
1306
|
-
|
|
1307
|
-
]),
|
|
1308
|
-
...
|
|
1309
|
-
ref:
|
|
1310
|
-
document:
|
|
1760
|
+
F
|
|
1761
|
+
]), v ? /* @__PURE__ */ h(Ae, {
|
|
1762
|
+
...p,
|
|
1763
|
+
ref: C,
|
|
1764
|
+
document: v,
|
|
1311
1765
|
ui: e.ui !== !1 && {
|
|
1312
1766
|
menu: !1,
|
|
1313
1767
|
print: !1,
|
|
1314
1768
|
...e.ui
|
|
1315
1769
|
},
|
|
1316
|
-
mode:
|
|
1317
|
-
actionsDisabled: e.actionsDisabled ||
|
|
1318
|
-
onChange:
|
|
1319
|
-
onStatusChange:
|
|
1320
|
-
}) : /* @__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", {
|
|
1321
1775
|
className: ["az-html-editor", e.className].filter(Boolean).join(" "),
|
|
1322
1776
|
style: e.style,
|
|
1323
|
-
children:
|
|
1324
|
-
role:
|
|
1325
|
-
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)) })]
|
|
1326
1780
|
})
|
|
1327
1781
|
});
|
|
1328
|
-
}),
|
|
1329
|
-
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) {
|
|
1330
1784
|
let t = new DOMParser().parseFromString(e, "application/xml");
|
|
1331
1785
|
if (t.getElementsByTagName("parsererror").length || /<!DOCTYPE/i.test(e)) throw Error("XML документа повреждён или содержит неподдерживаемую структуру.");
|
|
1332
1786
|
return t;
|
|
1333
1787
|
}
|
|
1334
|
-
function
|
|
1788
|
+
function Re(e, t) {
|
|
1335
1789
|
let n = e.file(t);
|
|
1336
1790
|
return n ? new Promise((e, t) => {
|
|
1337
1791
|
let r = n.internalStream("uint8array"), i = [], a = 0;
|
|
1338
1792
|
r.on("data", (e) => {
|
|
1339
|
-
a += e.byteLength, a >
|
|
1793
|
+
a += e.byteLength, a > Ie ? (r.pause(), t(/* @__PURE__ */ Error("Структура документа слишком большая для этого прототипа."))) : i.push(e);
|
|
1340
1794
|
}), r.on("error", t), r.on("end", () => {
|
|
1341
1795
|
let t = new Uint8Array(a), n = 0;
|
|
1342
1796
|
for (let e of i) t.set(e, n), n += e.byteLength;
|
|
@@ -1344,70 +1798,70 @@ function $(e, t) {
|
|
|
1344
1798
|
}), r.resume();
|
|
1345
1799
|
}) : Promise.resolve("");
|
|
1346
1800
|
}
|
|
1347
|
-
async function
|
|
1801
|
+
async function ze(e) {
|
|
1348
1802
|
if (!/\.docx$/i.test(e.name)) throw Error("Откройте файл DOCX. Форматы DOC, DOCM и PDF здесь не поддерживаются.");
|
|
1349
1803
|
if (!e.size) throw Error("Файл DOCX пуст.");
|
|
1350
1804
|
if (e.size > 31457280) throw Error("Максимальный размер DOCX — 30 МБ.");
|
|
1351
1805
|
let t = new Uint8Array(await e.arrayBuffer()), n;
|
|
1352
1806
|
try {
|
|
1353
|
-
n = await
|
|
1807
|
+
n = await p.loadAsync(t);
|
|
1354
1808
|
} catch {
|
|
1355
1809
|
throw Error("Файл повреждён, зашифрован или не является DOCX.");
|
|
1356
1810
|
}
|
|
1357
1811
|
let r = Object.keys(n.files);
|
|
1358
1812
|
if (r.length > 2e3) throw Error("Слишком много вложенных частей в DOCX для этого прототипа.");
|
|
1359
1813
|
if (!n.file("[Content_Types].xml") || !n.file("word/document.xml")) throw Error("Файл не содержит структуру DOCX.");
|
|
1360
|
-
let i =
|
|
1361
|
-
if (Array.from(i.getElementsByTagNameNS("*", "Override")).find((e) => e.getAttribute("PartName") === "/word/document.xml")?.getAttribute("ContentType") !==
|
|
1362
|
-
let a =
|
|
1363
|
-
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.");
|
|
1364
1818
|
let o = /* @__PURE__ */ new Set(), s = [a];
|
|
1365
1819
|
for (let e of ["word/styles.xml", "word/fontTable.xml"]) {
|
|
1366
|
-
let t = await
|
|
1367
|
-
t && s.push(
|
|
1820
|
+
let t = await Re(n, e);
|
|
1821
|
+
t && s.push(Le(t));
|
|
1368
1822
|
}
|
|
1369
1823
|
for (let e of s) {
|
|
1370
|
-
for (let t of e.getElementsByTagNameNS(
|
|
1824
|
+
for (let t of e.getElementsByTagNameNS($, "rFonts")) for (let e of [
|
|
1371
1825
|
"ascii",
|
|
1372
1826
|
"hAnsi",
|
|
1373
1827
|
"cs",
|
|
1374
1828
|
"eastAsia"
|
|
1375
1829
|
]) {
|
|
1376
|
-
let n = t.getAttributeNS(
|
|
1830
|
+
let n = t.getAttributeNS($, e);
|
|
1377
1831
|
n && o.add(n);
|
|
1378
1832
|
}
|
|
1379
|
-
for (let t of e.getElementsByTagNameNS(
|
|
1380
|
-
let e = t.getAttributeNS(
|
|
1833
|
+
for (let t of e.getElementsByTagNameNS($, "font")) {
|
|
1834
|
+
let e = t.getAttributeNS($, "name");
|
|
1381
1835
|
e && o.add(e);
|
|
1382
1836
|
}
|
|
1383
1837
|
}
|
|
1384
|
-
let c = await
|
|
1385
|
-
if (!
|
|
1386
|
-
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(), {
|
|
1387
1841
|
name: e.name,
|
|
1388
1842
|
original: t,
|
|
1389
1843
|
metadata: {
|
|
1390
|
-
paragraphs: a.getElementsByTagNameNS(
|
|
1391
|
-
tables: a.getElementsByTagNameNS(
|
|
1392
|
-
sections: a.getElementsByTagNameNS(
|
|
1844
|
+
paragraphs: a.getElementsByTagNameNS($, "p").length,
|
|
1845
|
+
tables: a.getElementsByTagNameNS($, "tbl").length,
|
|
1846
|
+
sections: a.getElementsByTagNameNS($, "sectPr").length,
|
|
1393
1847
|
savedPageCount: Number.isSafeInteger(l) && l > 0 ? l : null,
|
|
1394
1848
|
hasHeaders: r.some((e) => /^word\/header[^/]*\.xml$/.test(e)),
|
|
1395
1849
|
hasFooters: r.some((e) => /^word\/footer[^/]*\.xml$/.test(e)),
|
|
1396
|
-
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),
|
|
1397
1851
|
fonts: [...o].sort()
|
|
1398
1852
|
}
|
|
1399
1853
|
};
|
|
1400
1854
|
}
|
|
1401
|
-
function
|
|
1855
|
+
function Be(e) {
|
|
1402
1856
|
return `${(e.replace(/\.docx$/i, "").replace(/[<>:"/\\|?*\x00-\x1f]/g, "_").trim() || "Документ").replace(/ — редакция$/, "")} — редакция.docx`;
|
|
1403
1857
|
}
|
|
1404
|
-
function
|
|
1405
|
-
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");
|
|
1406
1860
|
r.href = n, r.download = t, document.body.append(r), r.click(), r.remove(), window.setTimeout(() => URL.revokeObjectURL(n), 3e4);
|
|
1407
1861
|
}
|
|
1408
1862
|
//#endregion
|
|
1409
1863
|
//#region src/library/pdf-export.ts
|
|
1410
|
-
async function
|
|
1864
|
+
async function He(e, t, n, r = {}) {
|
|
1411
1865
|
let i = AbortSignal.any([AbortSignal.timeout(95e3), ...r.signal ? [r.signal] : []]);
|
|
1412
1866
|
i.throwIfAborted();
|
|
1413
1867
|
let a = new FormData();
|
|
@@ -1436,13 +1890,13 @@ async function Oe(e, t, n, r = {}) {
|
|
|
1436
1890
|
warnings: (o.headers.get("x-pdf-warnings") ?? "").split(",").filter(Boolean)
|
|
1437
1891
|
};
|
|
1438
1892
|
}
|
|
1439
|
-
function
|
|
1893
|
+
function Ue(e) {
|
|
1440
1894
|
let t = URL.createObjectURL(e.blob), n = document.createElement("a");
|
|
1441
1895
|
n.href = t, n.download = e.filename, document.body.append(n), n.click(), n.remove(), setTimeout(() => URL.revokeObjectURL(t), 6e4);
|
|
1442
1896
|
}
|
|
1443
1897
|
//#endregion
|
|
1444
1898
|
//#region src/library/pdf-profile.ts
|
|
1445
|
-
var
|
|
1899
|
+
var We = {
|
|
1446
1900
|
id: "az-editor-pdf-a0c6eaaeb90716f0",
|
|
1447
1901
|
protocolVersion: 1,
|
|
1448
1902
|
core: "2.27.0",
|
|
@@ -1589,19 +2043,19 @@ var Ae = {
|
|
|
1589
2043
|
};
|
|
1590
2044
|
//#endregion
|
|
1591
2045
|
//#region src/library/hujjat/api.ts
|
|
1592
|
-
function
|
|
1593
|
-
if (!e || !Object.keys(e).length) throw new
|
|
2046
|
+
function Ge(e) {
|
|
2047
|
+
if (!e || !Object.keys(e).length) throw new A("Нет локалей шаблона.");
|
|
1594
2048
|
for (let [t, n] of Object.entries(e)) {
|
|
1595
|
-
if (
|
|
2049
|
+
if (L(t), !n || !Array.isArray(n.blocks) || !n.blocks.length) throw new A(`Нет блоков для ${t}.`);
|
|
1596
2050
|
for (let e of n.blocks) if (e.type === "html") {
|
|
1597
|
-
if (typeof e.props?.html != "string" || !e.props.html.trim()) throw new
|
|
1598
|
-
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 МБ.`);
|
|
1599
2053
|
}
|
|
1600
2054
|
}
|
|
1601
2055
|
}
|
|
1602
|
-
function
|
|
1603
|
-
if (
|
|
1604
|
-
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 символов.");
|
|
1605
2059
|
return {
|
|
1606
2060
|
product_id: e.productId,
|
|
1607
2061
|
name: e.name,
|
|
@@ -1609,11 +2063,11 @@ function Me(e, t) {
|
|
|
1609
2063
|
locales: structuredClone(t)
|
|
1610
2064
|
};
|
|
1611
2065
|
}
|
|
1612
|
-
async function
|
|
2066
|
+
async function qe(e) {
|
|
1613
2067
|
let t = AbortSignal.any([AbortSignal.timeout(95e3), ...e.signal ? [e.signal] : []]);
|
|
1614
|
-
t.throwIfAborted(),
|
|
2068
|
+
t.throwIfAborted(), Ge(e.locales);
|
|
1615
2069
|
let n = e.locale ?? "uz";
|
|
1616
|
-
|
|
2070
|
+
L(n);
|
|
1617
2071
|
let r = new Headers(e.headers);
|
|
1618
2072
|
r.set("Content-Type", "application/json"), r.set("Accept", "application/pdf, application/json");
|
|
1619
2073
|
let i = await (e.fetcher ?? fetch)(e.url, {
|
|
@@ -1641,4 +2095,4 @@ async function Ne(e) {
|
|
|
1641
2095
|
};
|
|
1642
2096
|
}
|
|
1643
2097
|
//#endregion
|
|
1644
|
-
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 };
|