autumnnote 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/autumnnote.css +0 -2
- package/dist/autumnnote.es.js +468 -552
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +461 -546
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +21 -3
- package/src/js/Context.js +21 -16
- package/src/js/core/dom.js +9 -9
- package/src/js/core/env.js +1 -1
- package/src/js/core/func.js +1 -1
- package/src/js/core/lists.js +1 -1
- package/src/js/core/markdown.js +18 -18
- package/src/js/core/range.js +6 -6
- package/src/js/editing/History.js +4 -4
- package/src/js/editing/Style.js +32 -32
- package/src/js/editing/Table.js +2 -2
- package/src/js/editing/Typing.js +15 -15
- package/src/js/index.js +1 -1
- package/src/js/module/AutoSaveRestore.js +2 -4
- package/src/js/module/BaseDialog.js +126 -0
- package/src/js/module/BubbleToolbar.js +25 -25
- package/src/js/module/Buttons.js +4 -4
- package/src/js/module/Clipboard.js +12 -13
- package/src/js/module/CodeTooltip.js +14 -16
- package/src/js/module/Codeview.js +3 -5
- package/src/js/module/ContextMenu.js +27 -27
- package/src/js/module/Editor.js +17 -18
- package/src/js/module/EmojiDialog.js +5 -5
- package/src/js/module/FindReplace.js +8 -7
- package/src/js/module/IconDialog.js +13 -15
- package/src/js/module/ImageCropOverlay.js +7 -7
- package/src/js/module/ImageDialog.js +12 -82
- package/src/js/module/ImageResizer.js +4 -4
- package/src/js/module/ImageTooltip.js +14 -14
- package/src/js/module/LinkDialog.js +13 -79
- package/src/js/module/LinkTooltip.js +12 -12
- package/src/js/module/MarkdownShortcuts.js +11 -14
- package/src/js/module/Mention.js +8 -10
- package/src/js/module/Placeholder.js +1 -1
- package/src/js/module/ShortcutsDialog.js +2 -4
- package/src/js/module/Statusbar.js +3 -5
- package/src/js/module/TableTooltip.js +30 -32
- package/src/js/module/Toolbar.js +21 -21
- package/src/js/module/VideoDialog.js +17 -87
- package/src/js/module/VideoResizer.js +5 -7
- package/src/js/module/VideoTooltip.js +7 -7
- package/src/js/renderer.js +1 -1
- package/src/styles/autumnnote.scss +0 -3
package/dist/autumnnote.umd.js
CHANGED
|
@@ -114,14 +114,14 @@
|
|
|
114
114
|
const handler = (e) => {
|
|
115
115
|
if (e.key === "Escape") {
|
|
116
116
|
e.stopPropagation();
|
|
117
|
-
onEscape
|
|
117
|
+
onEscape?.();
|
|
118
118
|
return;
|
|
119
119
|
}
|
|
120
120
|
if (e.key !== "Tab") return;
|
|
121
121
|
const els = getFocusable();
|
|
122
122
|
if (!els.length) return;
|
|
123
123
|
const first = els[0];
|
|
124
|
-
const last = els
|
|
124
|
+
const last = els.at(-1);
|
|
125
125
|
if (e.shiftKey) {
|
|
126
126
|
if (document.activeElement === first) {
|
|
127
127
|
e.preventDefault();
|
|
@@ -159,14 +159,14 @@
|
|
|
159
159
|
box.style.top = `${r.top}px`;
|
|
160
160
|
box.dataset.anDragPinned = "1";
|
|
161
161
|
}
|
|
162
|
-
const startX = e.clientX - parseFloat(box.style.left);
|
|
163
|
-
const startY = e.clientY - parseFloat(box.style.top);
|
|
162
|
+
const startX = e.clientX - Number.parseFloat(box.style.left);
|
|
163
|
+
const startY = e.clientY - Number.parseFloat(box.style.top);
|
|
164
164
|
handle.style.cursor = "grabbing";
|
|
165
165
|
const onMove = (ev) => {
|
|
166
166
|
const bw = box.offsetWidth;
|
|
167
167
|
const bh = box.offsetHeight;
|
|
168
|
-
box.style.left = `${Math.max(0, Math.min(ev.clientX - startX,
|
|
169
|
-
box.style.top = `${Math.max(0, Math.min(ev.clientY - startY,
|
|
168
|
+
box.style.left = `${Math.max(0, Math.min(ev.clientX - startX, globalThis.innerWidth - bw))}px`;
|
|
169
|
+
box.style.top = `${Math.max(0, Math.min(ev.clientY - startY, globalThis.innerHeight - bh))}px`;
|
|
170
170
|
};
|
|
171
171
|
const onUp = () => {
|
|
172
172
|
handle.style.cursor = "grab";
|
|
@@ -212,10 +212,10 @@
|
|
|
212
212
|
return range;
|
|
213
213
|
}
|
|
214
214
|
/**
|
|
215
|
-
* Select this wrapped range in the
|
|
215
|
+
* Select this wrapped range in the globalThis.
|
|
216
216
|
*/
|
|
217
217
|
select() {
|
|
218
|
-
const sel =
|
|
218
|
+
const sel = globalThis.getSelection();
|
|
219
219
|
if (!sel) return;
|
|
220
220
|
sel.removeAllRanges();
|
|
221
221
|
sel.addRange(this.toNativeRange());
|
|
@@ -268,13 +268,13 @@
|
|
|
268
268
|
return new WrappedRange(range.startContainer, range.startOffset, range.endContainer, range.endOffset);
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
|
-
* Returns a WrappedRange for the current
|
|
271
|
+
* Returns a WrappedRange for the current globalThis selection,
|
|
272
272
|
* optionally restricted to a given editable element.
|
|
273
273
|
* @param {HTMLElement} [editable]
|
|
274
274
|
* @returns {WrappedRange|null}
|
|
275
275
|
*/
|
|
276
276
|
function currentRange(editable) {
|
|
277
|
-
const sel =
|
|
277
|
+
const sel = globalThis.getSelection();
|
|
278
278
|
if (!sel || sel.rangeCount === 0) return null;
|
|
279
279
|
const native = sel.getRangeAt(0);
|
|
280
280
|
if (editable && !editable.contains(native.commonAncestorContainer)) return null;
|
|
@@ -285,7 +285,7 @@
|
|
|
285
285
|
* @param {Function} fn
|
|
286
286
|
*/
|
|
287
287
|
function withSavedRange(fn) {
|
|
288
|
-
const sel =
|
|
288
|
+
const sel = globalThis.getSelection();
|
|
289
289
|
if (!sel || sel.rangeCount === 0) {
|
|
290
290
|
fn(null);
|
|
291
291
|
return;
|
|
@@ -320,16 +320,16 @@
|
|
|
320
320
|
* execCommand's state detection is unreliable.
|
|
321
321
|
*/
|
|
322
322
|
function underline() {
|
|
323
|
-
const sel =
|
|
323
|
+
const sel = globalThis.getSelection();
|
|
324
324
|
if (!sel || !sel.rangeCount) return;
|
|
325
325
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
326
326
|
if (container.nodeType === 3) container = container.parentElement;
|
|
327
|
-
const uEl = container
|
|
327
|
+
const uEl = container?.closest("u");
|
|
328
328
|
const nativeState = document.queryCommandState("underline");
|
|
329
329
|
if (uEl && !nativeState) {
|
|
330
330
|
const parent = uEl.parentNode;
|
|
331
331
|
while (uEl.firstChild) parent.insertBefore(uEl.firstChild, uEl);
|
|
332
|
-
|
|
332
|
+
uEl.remove();
|
|
333
333
|
return;
|
|
334
334
|
}
|
|
335
335
|
execCommand("underline");
|
|
@@ -340,16 +340,16 @@
|
|
|
340
340
|
* execCommand's state detection is unreliable (mirrors underline() logic).
|
|
341
341
|
*/
|
|
342
342
|
function strikethrough() {
|
|
343
|
-
const sel =
|
|
343
|
+
const sel = globalThis.getSelection();
|
|
344
344
|
if (!sel || !sel.rangeCount) return;
|
|
345
345
|
let sc = sel.getRangeAt(0).startContainer;
|
|
346
346
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
347
|
-
const sEl = sc
|
|
347
|
+
const sEl = sc?.closest("s") || sc?.closest("strike");
|
|
348
348
|
const nativeState = document.queryCommandState("strikeThrough");
|
|
349
349
|
if (sEl && !nativeState) {
|
|
350
350
|
const parent = sEl.parentNode;
|
|
351
351
|
while (sEl.firstChild) parent.insertBefore(sEl.firstChild, sEl);
|
|
352
|
-
|
|
352
|
+
sEl.remove();
|
|
353
353
|
return;
|
|
354
354
|
}
|
|
355
355
|
execCommand("strikeThrough");
|
|
@@ -384,7 +384,7 @@
|
|
|
384
384
|
* @param {HTMLElement|Document} [editable] - scoping element to avoid touching nodes outside this editor
|
|
385
385
|
*/
|
|
386
386
|
function fontSize(size, editable = document) {
|
|
387
|
-
const sel =
|
|
387
|
+
const sel = globalThis.getSelection();
|
|
388
388
|
const wasCollapsed = !sel || !sel.rangeCount || sel.getRangeAt(0).collapsed;
|
|
389
389
|
if (wasCollapsed && sel && sel.rangeCount > 0) {
|
|
390
390
|
try {
|
|
@@ -410,12 +410,12 @@
|
|
|
410
410
|
span.style.fontSize = size;
|
|
411
411
|
el.parentNode.insertBefore(span, el);
|
|
412
412
|
while (el.firstChild) span.appendChild(el.firstChild);
|
|
413
|
-
el.
|
|
413
|
+
el.remove();
|
|
414
414
|
newSpans.push(span);
|
|
415
415
|
});
|
|
416
416
|
if (!wasCollapsed && sel && newSpans.length > 0) {
|
|
417
417
|
const first = newSpans[0];
|
|
418
|
-
const last = newSpans
|
|
418
|
+
const last = newSpans.at(-1);
|
|
419
419
|
try {
|
|
420
420
|
const nr = document.createRange();
|
|
421
421
|
const startNode = first.firstChild || first;
|
|
@@ -459,11 +459,11 @@
|
|
|
459
459
|
* (which would destroy the ul > li checklist structure).
|
|
460
460
|
*/
|
|
461
461
|
function outdent() {
|
|
462
|
-
const sel =
|
|
462
|
+
const sel = globalThis.getSelection();
|
|
463
463
|
if (sel && sel.rangeCount) {
|
|
464
464
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
465
465
|
if (container.nodeType === 3) container = container.parentElement;
|
|
466
|
-
const checkLi = container
|
|
466
|
+
const checkLi = container?.closest(".an-checklist li");
|
|
467
467
|
if (checkLi) {
|
|
468
468
|
_checklistItemToP(checkLi);
|
|
469
469
|
return;
|
|
@@ -493,7 +493,7 @@
|
|
|
493
493
|
if (child.nodeType === 1 && child.tagName === "INPUT") continue;
|
|
494
494
|
p.appendChild(child.cloneNode(true));
|
|
495
495
|
}
|
|
496
|
-
p.innerHTML = p.innerHTML.
|
|
496
|
+
p.innerHTML = p.innerHTML.replaceAll("", "");
|
|
497
497
|
if (!p.hasChildNodes() || !p.textContent.trim()) {
|
|
498
498
|
p.innerHTML = "";
|
|
499
499
|
p.appendChild(document.createTextNode("\xA0"));
|
|
@@ -505,14 +505,14 @@
|
|
|
505
505
|
checkUl.parentNode.insertBefore(newUl, checkUl.nextSibling);
|
|
506
506
|
}
|
|
507
507
|
checkUl.parentNode.insertBefore(p, checkUl.nextSibling);
|
|
508
|
-
|
|
509
|
-
if (checkUl.children.length === 0) checkUl.
|
|
508
|
+
checkLi.remove();
|
|
509
|
+
if (checkUl.children.length === 0) checkUl.remove();
|
|
510
510
|
try {
|
|
511
511
|
const nr = document.createRange();
|
|
512
512
|
const firstChild = p.firstChild;
|
|
513
513
|
nr.setStart(firstChild && firstChild.nodeType === 3 ? firstChild : p, 0);
|
|
514
514
|
nr.collapse(true);
|
|
515
|
-
const s =
|
|
515
|
+
const s = globalThis.getSelection();
|
|
516
516
|
if (s) {
|
|
517
517
|
s.removeAllRanges();
|
|
518
518
|
s.addRange(nr);
|
|
@@ -536,7 +536,7 @@
|
|
|
536
536
|
* @param {string} value - Line-height value to apply; typically a unitless multiplier (for example, "1.5").
|
|
537
537
|
*/
|
|
538
538
|
function lineHeight(value) {
|
|
539
|
-
const sel =
|
|
539
|
+
const sel = globalThis.getSelection();
|
|
540
540
|
if (!sel || sel.rangeCount === 0) return;
|
|
541
541
|
const range = sel.getRangeAt(0);
|
|
542
542
|
const BLOCK_TAGS = new Set([
|
|
@@ -588,22 +588,22 @@
|
|
|
588
588
|
* @param {HTMLElement} [_editable]
|
|
589
589
|
*/
|
|
590
590
|
function toggleInlineCode(_editable) {
|
|
591
|
-
const sel =
|
|
591
|
+
const sel = globalThis.getSelection();
|
|
592
592
|
if (!sel || !sel.rangeCount) return;
|
|
593
593
|
const range = sel.getRangeAt(0);
|
|
594
594
|
let container = range.commonAncestorContainer;
|
|
595
595
|
if (container.nodeType === 3) container = container.parentElement;
|
|
596
|
-
const codeEl = container
|
|
596
|
+
const codeEl = container?.closest("code");
|
|
597
597
|
if (codeEl && !codeEl.closest("pre")) {
|
|
598
598
|
const parent = codeEl.parentNode;
|
|
599
599
|
const prevSibling = codeEl.previousSibling;
|
|
600
600
|
const movedChildren = Array.from(codeEl.childNodes);
|
|
601
601
|
while (codeEl.firstChild) parent.insertBefore(codeEl.firstChild, codeEl);
|
|
602
|
-
|
|
603
|
-
|
|
602
|
+
codeEl.remove();
|
|
603
|
+
parent?.normalize();
|
|
604
604
|
if (movedChildren.length > 0) try {
|
|
605
605
|
const firstMoved = movedChildren[0];
|
|
606
|
-
const lastMoved = movedChildren
|
|
606
|
+
const lastMoved = movedChildren.at(-1);
|
|
607
607
|
const nr = document.createRange();
|
|
608
608
|
const anchorNode = firstMoved.parentNode === parent ? firstMoved : prevSibling ? prevSibling.nextSibling : parent.firstChild;
|
|
609
609
|
if (anchorNode) {
|
|
@@ -644,11 +644,11 @@
|
|
|
644
644
|
* @returns {boolean}
|
|
645
645
|
*/
|
|
646
646
|
function isInlineCode() {
|
|
647
|
-
const sel =
|
|
647
|
+
const sel = globalThis.getSelection();
|
|
648
648
|
if (!sel || !sel.rangeCount) return false;
|
|
649
649
|
let sc = sel.getRangeAt(0).startContainer;
|
|
650
650
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
651
|
-
const code = sc
|
|
651
|
+
const code = sc?.closest("code");
|
|
652
652
|
return !!(code && !code.closest("pre"));
|
|
653
653
|
}
|
|
654
654
|
/**
|
|
@@ -666,12 +666,12 @@
|
|
|
666
666
|
* Empty or whitespace-only selections do not create a checklist.
|
|
667
667
|
*/
|
|
668
668
|
function toggleChecklist() {
|
|
669
|
-
const sel =
|
|
669
|
+
const sel = globalThis.getSelection();
|
|
670
670
|
if (!sel || !sel.rangeCount) return;
|
|
671
671
|
const range = sel.getRangeAt(0);
|
|
672
672
|
let container = range.commonAncestorContainer;
|
|
673
673
|
if (container.nodeType === 3) container = container.parentElement;
|
|
674
|
-
const ul = container
|
|
674
|
+
const ul = container?.closest(".an-checklist");
|
|
675
675
|
if (ul) {
|
|
676
676
|
const selectedLis = Array.from(ul.querySelectorAll("li")).filter((li) => sel.containsNode(li, true));
|
|
677
677
|
if (selectedLis.length > 0) {
|
|
@@ -682,14 +682,14 @@
|
|
|
682
682
|
if (child.nodeType === 1 && child.tagName === "INPUT") continue;
|
|
683
683
|
p.appendChild(child.cloneNode(true));
|
|
684
684
|
}
|
|
685
|
-
p.innerHTML = p.innerHTML.
|
|
685
|
+
p.innerHTML = p.innerHTML.replaceAll("", "");
|
|
686
686
|
if (!p.hasChildNodes() || !p.textContent.trim()) {
|
|
687
687
|
p.innerHTML = "";
|
|
688
688
|
p.appendChild(document.createTextNode("\xA0"));
|
|
689
689
|
}
|
|
690
690
|
ul.parentNode.insertBefore(p, ul);
|
|
691
691
|
if (!firstP) firstP = p;
|
|
692
|
-
|
|
692
|
+
li.remove();
|
|
693
693
|
});
|
|
694
694
|
if (ul.children.length === 0) ul.remove();
|
|
695
695
|
if (firstP) {
|
|
@@ -717,7 +717,7 @@
|
|
|
717
717
|
]);
|
|
718
718
|
let block = container;
|
|
719
719
|
while (block && block.parentNode && !BLOCK_TAGS.has(block.tagName)) block = block.parentNode;
|
|
720
|
-
const itemText = block && BLOCK_TAGS.has(block.tagName) ? Array.from(block.childNodes).map((n) => n.textContent).join("").
|
|
720
|
+
const itemText = block && BLOCK_TAGS.has(block.tagName) ? Array.from(block.childNodes).map((n) => n.textContent).join("").replaceAll("\xA0", " ") : "";
|
|
721
721
|
const ul = document.createElement("ul");
|
|
722
722
|
ul.className = "an-checklist";
|
|
723
723
|
const li = document.createElement("li");
|
|
@@ -788,7 +788,7 @@
|
|
|
788
788
|
});
|
|
789
789
|
const firstBlock = blocks[0];
|
|
790
790
|
firstBlock.parentNode.insertBefore(newUl, firstBlock);
|
|
791
|
-
blocks.forEach((block) => block.
|
|
791
|
+
blocks.forEach((block) => block.remove());
|
|
792
792
|
if (lastTextNode) {
|
|
793
793
|
const nr = document.createRange();
|
|
794
794
|
nr.setStart(lastTextNode, lastTextNode.textContent.length);
|
|
@@ -802,11 +802,11 @@
|
|
|
802
802
|
* @returns {boolean}
|
|
803
803
|
*/
|
|
804
804
|
function isInChecklist() {
|
|
805
|
-
const sel =
|
|
805
|
+
const sel = globalThis.getSelection();
|
|
806
806
|
if (!sel || !sel.rangeCount) return false;
|
|
807
807
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
808
808
|
if (container.nodeType === 3) container = container.parentElement;
|
|
809
|
-
return !!
|
|
809
|
+
return !!container?.closest(".an-checklist li");
|
|
810
810
|
}
|
|
811
811
|
//#endregion
|
|
812
812
|
//#region src/js/module/Buttons.js
|
|
@@ -888,7 +888,7 @@
|
|
|
888
888
|
var italicBtn = btn("italic", "italic", "Italic (Ctrl+I)", () => italic(), () => document.queryCommandState("italic"));
|
|
889
889
|
var underlineBtn = btn("underline", "underline", "Underline (Ctrl+U)", () => underline(), () => {
|
|
890
890
|
if (document.queryCommandState("underline")) return true;
|
|
891
|
-
const sel =
|
|
891
|
+
const sel = globalThis.getSelection();
|
|
892
892
|
if (!sel || !sel.rangeCount) return false;
|
|
893
893
|
let sc = sel.getRangeAt(0).startContainer;
|
|
894
894
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
@@ -951,7 +951,7 @@
|
|
|
951
951
|
action: (ctx, value) => fontSize(value, ctx.layoutInfo.editable),
|
|
952
952
|
getValue: (ctx) => {
|
|
953
953
|
try {
|
|
954
|
-
const sel =
|
|
954
|
+
const sel = globalThis.getSelection();
|
|
955
955
|
if (sel && sel.rangeCount) {
|
|
956
956
|
let el = sel.getRangeAt(0).startContainer;
|
|
957
957
|
if (el && el.nodeType === 3) el = el.parentElement;
|
|
@@ -959,7 +959,7 @@
|
|
|
959
959
|
const size = el && el.style.fontSize ? el.style.fontSize : "";
|
|
960
960
|
if (size) return size;
|
|
961
961
|
}
|
|
962
|
-
const editable = ctx
|
|
962
|
+
const editable = ctx?.layoutInfo?.editable;
|
|
963
963
|
if (editable) return editable.style.fontSize || "";
|
|
964
964
|
return "";
|
|
965
965
|
} catch {
|
|
@@ -1056,7 +1056,7 @@
|
|
|
1056
1056
|
action: (_ctx, value) => lineHeight(value),
|
|
1057
1057
|
getValue: () => {
|
|
1058
1058
|
try {
|
|
1059
|
-
const sel =
|
|
1059
|
+
const sel = globalThis.getSelection();
|
|
1060
1060
|
if (!sel || !sel.rangeCount) return "";
|
|
1061
1061
|
const BLOCKS = new Set([
|
|
1062
1062
|
"P",
|
|
@@ -4171,7 +4171,7 @@
|
|
|
4171
4171
|
} catch (_) {}
|
|
4172
4172
|
if (!initialContent) initialContent = targetEl.tagName === "TEXTAREA" ? (targetEl.value || "").trim() : (targetEl.innerHTML || "").trim();
|
|
4173
4173
|
editable.innerHTML = sanitiseHTML(initialContent, { allowIframes: true });
|
|
4174
|
-
const defaultFont = options.defaultFontFamily || options.fontFamilies
|
|
4174
|
+
const defaultFont = options.defaultFontFamily || options.fontFamilies?.[0];
|
|
4175
4175
|
if (defaultFont) editable.style.fontFamily = defaultFont;
|
|
4176
4176
|
if (options.defaultFontSize) editable.style.fontSize = options.defaultFontSize;
|
|
4177
4177
|
if (options.height) editable.style.minHeight = `${options.height}px`;
|
|
@@ -4233,7 +4233,7 @@
|
|
|
4233
4233
|
* @returns {{ start: number, end: number }|null}
|
|
4234
4234
|
*/
|
|
4235
4235
|
_serializeSelection() {
|
|
4236
|
-
const sel =
|
|
4236
|
+
const sel = globalThis.getSelection();
|
|
4237
4237
|
if (!sel || sel.rangeCount === 0) return null;
|
|
4238
4238
|
const range = sel.getRangeAt(0);
|
|
4239
4239
|
if (!this.editable.contains(range.startContainer)) return null;
|
|
@@ -4299,7 +4299,7 @@
|
|
|
4299
4299
|
const range = document.createRange();
|
|
4300
4300
|
range.setStart(startNode, startOff);
|
|
4301
4301
|
range.setEnd(endNode, endOff);
|
|
4302
|
-
const sel =
|
|
4302
|
+
const sel = globalThis.getSelection();
|
|
4303
4303
|
sel.removeAllRanges();
|
|
4304
4304
|
sel.addRange(range);
|
|
4305
4305
|
} catch (_) {
|
|
@@ -4307,7 +4307,7 @@
|
|
|
4307
4307
|
const fb = document.createRange();
|
|
4308
4308
|
fb.setStart(this.editable, 0);
|
|
4309
4309
|
fb.collapse(true);
|
|
4310
|
-
const s =
|
|
4310
|
+
const s = globalThis.getSelection();
|
|
4311
4311
|
if (s) {
|
|
4312
4312
|
s.removeAllRanges();
|
|
4313
4313
|
s.addRange(fb);
|
|
@@ -4371,8 +4371,7 @@
|
|
|
4371
4371
|
recordUndo() {
|
|
4372
4372
|
const current = this._serialize();
|
|
4373
4373
|
const { html: tokenized } = this._tokenizeImages(current);
|
|
4374
|
-
|
|
4375
|
-
if (prev && prev.html === tokenized) return;
|
|
4374
|
+
if (this.stack[this.stackOffset]?.html === tokenized) return;
|
|
4376
4375
|
this._savePoint();
|
|
4377
4376
|
}
|
|
4378
4377
|
/**
|
|
@@ -4456,7 +4455,7 @@
|
|
|
4456
4455
|
function insertTable(cols, rows, opts = {}) {
|
|
4457
4456
|
if (cols <= 0 || rows <= 0) return;
|
|
4458
4457
|
const table = createTable(cols, rows, opts);
|
|
4459
|
-
const sel =
|
|
4458
|
+
const sel = globalThis.getSelection();
|
|
4460
4459
|
if (!sel || sel.rangeCount === 0) return;
|
|
4461
4460
|
const range = sel.getRangeAt(0);
|
|
4462
4461
|
range.deleteContents();
|
|
@@ -4474,7 +4473,7 @@
|
|
|
4474
4473
|
"PRE"
|
|
4475
4474
|
]);
|
|
4476
4475
|
let anchor = range.startContainer;
|
|
4477
|
-
if (anchor
|
|
4476
|
+
if (anchor?.nodeType === 3) anchor = anchor.parentElement;
|
|
4478
4477
|
while (anchor && !BLOCK.has(anchor.tagName?.toUpperCase()) && anchor.parentElement) anchor = anchor.parentElement;
|
|
4479
4478
|
if (anchor && BLOCK.has(anchor.tagName?.toUpperCase()) && anchor.parentNode) {
|
|
4480
4479
|
anchor.after(table);
|
|
@@ -4564,8 +4563,8 @@
|
|
|
4564
4563
|
* Inspired by Summernote's Typing module
|
|
4565
4564
|
*/
|
|
4566
4565
|
var _FA_PATTERN = /\bfa-/;
|
|
4567
|
-
var isFAIcon = (n) => !!(n
|
|
4568
|
-
var isZwsAnchor = (n) => !!(n
|
|
4566
|
+
var isFAIcon = (n) => !!(n?.nodeName === "I" && _FA_PATTERN.test(n.className || ""));
|
|
4567
|
+
var isZwsAnchor = (n) => !!(n?.nodeType === Node.TEXT_NODE && (n.textContent === "" || n.textContent === ""));
|
|
4569
4568
|
/**
|
|
4570
4569
|
* Handles special keydown behaviour inside the editor.
|
|
4571
4570
|
* @param {KeyboardEvent} event
|
|
@@ -4575,7 +4574,7 @@
|
|
|
4575
4574
|
*/
|
|
4576
4575
|
function handleKeydown(event, editable, options = {}) {
|
|
4577
4576
|
const moveCaret = (setFn) => {
|
|
4578
|
-
const sel =
|
|
4577
|
+
const sel = globalThis.getSelection();
|
|
4579
4578
|
if (!sel) return false;
|
|
4580
4579
|
const nr = document.createRange();
|
|
4581
4580
|
setFn(nr);
|
|
@@ -4585,8 +4584,8 @@
|
|
|
4585
4584
|
return true;
|
|
4586
4585
|
};
|
|
4587
4586
|
if (isKey(event, key.BACKSPACE)) {
|
|
4588
|
-
const sel =
|
|
4589
|
-
if (sel
|
|
4587
|
+
const sel = globalThis.getSelection();
|
|
4588
|
+
if (sel?.rangeCount > 0) {
|
|
4590
4589
|
const r = sel.getRangeAt(0);
|
|
4591
4590
|
if (r.collapsed && r.startContainer.nodeType === Node.TEXT_NODE) {
|
|
4592
4591
|
const textNode = r.startContainer;
|
|
@@ -4616,7 +4615,7 @@
|
|
|
4616
4615
|
return false;
|
|
4617
4616
|
}
|
|
4618
4617
|
if (isKey(event, key.LEFT) || isKey(event, key.RIGHT)) {
|
|
4619
|
-
const sel =
|
|
4618
|
+
const sel = globalThis.getSelection();
|
|
4620
4619
|
if (!sel || sel.rangeCount === 0) return false;
|
|
4621
4620
|
const r = sel.getRangeAt(0);
|
|
4622
4621
|
if (!r.collapsed) return false;
|
|
@@ -4704,7 +4703,7 @@
|
|
|
4704
4703
|
else execCommand("indent");
|
|
4705
4704
|
return true;
|
|
4706
4705
|
}
|
|
4707
|
-
if (para
|
|
4706
|
+
if (para?.nodeName.toUpperCase() === "PRE") {
|
|
4708
4707
|
if (event.shiftKey) return false;
|
|
4709
4708
|
event.preventDefault();
|
|
4710
4709
|
execCommand("insertText", " ".repeat(options.tabSize || 4));
|
|
@@ -4727,18 +4726,18 @@
|
|
|
4727
4726
|
if (!range) return false;
|
|
4728
4727
|
const sc = range.sc;
|
|
4729
4728
|
const el = sc.nodeType === 3 ? sc.parentElement : sc;
|
|
4730
|
-
if (el
|
|
4729
|
+
if (el?.nodeName === "I" && /\bfa-/.test(el.className || "")) {
|
|
4731
4730
|
const nr = document.createRange();
|
|
4732
4731
|
nr.setStartAfter(el);
|
|
4733
4732
|
nr.collapse(true);
|
|
4734
|
-
const selI =
|
|
4733
|
+
const selI = globalThis.getSelection();
|
|
4735
4734
|
if (selI) {
|
|
4736
4735
|
selI.removeAllRanges();
|
|
4737
4736
|
selI.addRange(nr);
|
|
4738
4737
|
}
|
|
4739
4738
|
return false;
|
|
4740
4739
|
}
|
|
4741
|
-
const videoWrapper = el
|
|
4740
|
+
const videoWrapper = el?.closest(".an-video-wrapper");
|
|
4742
4741
|
if (videoWrapper) {
|
|
4743
4742
|
event.preventDefault();
|
|
4744
4743
|
const p = document.createElement("p");
|
|
@@ -4747,16 +4746,16 @@
|
|
|
4747
4746
|
const nr = document.createRange();
|
|
4748
4747
|
nr.setStart(p, 0);
|
|
4749
4748
|
nr.collapse(true);
|
|
4750
|
-
const sel =
|
|
4749
|
+
const sel = globalThis.getSelection();
|
|
4751
4750
|
sel.removeAllRanges();
|
|
4752
4751
|
sel.addRange(nr);
|
|
4753
4752
|
return true;
|
|
4754
4753
|
}
|
|
4755
|
-
const checkLi = el
|
|
4754
|
+
const checkLi = el?.closest(".an-checklist li");
|
|
4756
4755
|
if (checkLi) {
|
|
4757
4756
|
event.preventDefault();
|
|
4758
4757
|
const ul = checkLi.closest(".an-checklist");
|
|
4759
|
-
const sel =
|
|
4758
|
+
const sel = globalThis.getSelection();
|
|
4760
4759
|
let nativeRange = sel.getRangeAt(0);
|
|
4761
4760
|
const liText = (li) => Array.from(li.childNodes).filter((n) => !(n.nodeType === 1 && n.tagName === "INPUT")).map((n) => n.textContent).join("").replace(/[\u00a0\u200B]/g, " ").trim();
|
|
4762
4761
|
if (!liText(checkLi)) {
|
|
@@ -4800,12 +4799,12 @@
|
|
|
4800
4799
|
return true;
|
|
4801
4800
|
}
|
|
4802
4801
|
const para = closestPara(range.sc, editable);
|
|
4803
|
-
if (para
|
|
4802
|
+
if (para?.nodeName.toUpperCase() === "PRE") {
|
|
4804
4803
|
event.preventDefault();
|
|
4805
4804
|
execCommand("insertText", "\n");
|
|
4806
4805
|
return true;
|
|
4807
4806
|
}
|
|
4808
|
-
if (para
|
|
4807
|
+
if (para?.nodeName.toUpperCase() === "BLOCKQUOTE") {
|
|
4809
4808
|
const native = range.toNativeRange();
|
|
4810
4809
|
native.setEnd(para, para.childNodes.length);
|
|
4811
4810
|
if (native.toString() === "" && range.isCollapsed()) {
|
|
@@ -4879,7 +4878,7 @@
|
|
|
4879
4878
|
return `\`${inner()}\``;
|
|
4880
4879
|
case "pre": {
|
|
4881
4880
|
const codeEl = el.querySelector("code");
|
|
4882
|
-
const langMatch = (codeEl && codeEl.className || "")
|
|
4881
|
+
const langMatch = /language-(\S+)/.exec(codeEl && codeEl.className || "");
|
|
4883
4882
|
return `\n\n\`\`\`${langMatch ? langMatch[1] : ""}\n${(codeEl || el).textContent || ""}\n\`\`\`\n\n`;
|
|
4884
4883
|
}
|
|
4885
4884
|
case "blockquote": return `\n\n${inner().trim().split("\n").map((l) => `> ${l}`).join("\n")}\n\n`;
|
|
@@ -4910,7 +4909,7 @@
|
|
|
4910
4909
|
case "table": {
|
|
4911
4910
|
const rows = Array.from(el.querySelectorAll("tr"));
|
|
4912
4911
|
if (!rows.length) return inner();
|
|
4913
|
-
const cellTexts = rows.map((tr) => Array.from(tr.querySelectorAll("th, td")).map((c) => c.textContent.trim().
|
|
4912
|
+
const cellTexts = rows.map((tr) => Array.from(tr.querySelectorAll("th, td")).map((c) => c.textContent.trim().replaceAll("|", "\\|")));
|
|
4914
4913
|
const cols = Math.max(...cellTexts.map((r) => r.length));
|
|
4915
4914
|
const padRow = (row) => {
|
|
4916
4915
|
const r = [...row];
|
|
@@ -4919,7 +4918,7 @@
|
|
|
4919
4918
|
};
|
|
4920
4919
|
let md = "\n\n";
|
|
4921
4920
|
md += `| ${padRow(cellTexts[0]).join(" | ")} |\n`;
|
|
4922
|
-
md += `| ${Array(cols).fill("---").join(" | ")} |\n`;
|
|
4921
|
+
md += `| ${new Array(cols).fill("---").join(" | ")} |\n`;
|
|
4923
4922
|
for (let r = 1; r < cellTexts.length; r++) md += `| ${padRow(cellTexts[r]).join(" | ")} |\n`;
|
|
4924
4923
|
return md + "\n";
|
|
4925
4924
|
}
|
|
@@ -4943,12 +4942,12 @@
|
|
|
4943
4942
|
* @returns {string}
|
|
4944
4943
|
*/
|
|
4945
4944
|
function markdownToHTML(text) {
|
|
4946
|
-
const lines = text.
|
|
4945
|
+
const lines = text.replaceAll("\r\n", "\n").replaceAll("\r", "\n").split("\n");
|
|
4947
4946
|
const out = [];
|
|
4948
4947
|
let i = 0;
|
|
4949
4948
|
while (i < lines.length) {
|
|
4950
4949
|
const line = lines[i];
|
|
4951
|
-
const fenceMatch =
|
|
4950
|
+
const fenceMatch = /^```(\S*)$/.exec(line);
|
|
4952
4951
|
if (fenceMatch) {
|
|
4953
4952
|
const lang = fenceMatch[1];
|
|
4954
4953
|
const codeLines = [];
|
|
@@ -4967,7 +4966,7 @@
|
|
|
4967
4966
|
i++;
|
|
4968
4967
|
continue;
|
|
4969
4968
|
}
|
|
4970
|
-
const hMatch =
|
|
4969
|
+
const hMatch = /^(#{1,6})\s+(.+)$/.exec(line);
|
|
4971
4970
|
if (hMatch) {
|
|
4972
4971
|
const level = hMatch[1].length;
|
|
4973
4972
|
out.push(`<h${level}>${_inline(hMatch[2])}</h${level}>`);
|
|
@@ -5014,7 +5013,8 @@
|
|
|
5014
5013
|
i++;
|
|
5015
5014
|
}
|
|
5016
5015
|
const thead = `<thead><tr>${headerCells.map((c) => `<th>${_inline(c)}</th>`).join("")}</tr></thead>`;
|
|
5017
|
-
const
|
|
5016
|
+
const renderRow = (row) => `<tr>${row.map((c) => `<td>${_inline(c)}</td>`).join("")}</tr>`;
|
|
5017
|
+
const tbody = bodyRows.length ? `<tbody>${bodyRows.map(renderRow).join("")}</tbody>` : "";
|
|
5018
5018
|
out.push(`<table>${thead}${tbody}</table>`);
|
|
5019
5019
|
continue;
|
|
5020
5020
|
}
|
|
@@ -5050,10 +5050,10 @@
|
|
|
5050
5050
|
return text;
|
|
5051
5051
|
}
|
|
5052
5052
|
function _esc(v) {
|
|
5053
|
-
return String(v).
|
|
5053
|
+
return String(v).replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
5054
5054
|
}
|
|
5055
5055
|
function _escAttr(v) {
|
|
5056
|
-
return String(v).
|
|
5056
|
+
return String(v).replaceAll("&", "&").replaceAll("\"", """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">");
|
|
5057
5057
|
}
|
|
5058
5058
|
//#endregion
|
|
5059
5059
|
//#region src/js/core/detectLang.js
|
|
@@ -5135,7 +5135,7 @@
|
|
|
5135
5135
|
const onBeforeInput = (event) => this._enforceLimit(event);
|
|
5136
5136
|
const onSelChange = () => {
|
|
5137
5137
|
if (!this.context._alive) return;
|
|
5138
|
-
const sel =
|
|
5138
|
+
const sel = globalThis.getSelection();
|
|
5139
5139
|
if (sel && sel.rangeCount > 0 && editable.contains(sel.anchorNode)) {
|
|
5140
5140
|
this.context.invoke("toolbar.refresh");
|
|
5141
5141
|
if (typeof this.options.onSelectionChange === "function") this.options.onSelectionChange(this.context);
|
|
@@ -5145,7 +5145,7 @@
|
|
|
5145
5145
|
if (e.target.type === "checkbox" && e.target.closest(".an-checklist")) this.afterCommand();
|
|
5146
5146
|
};
|
|
5147
5147
|
const fixChecklistCursor = (event) => {
|
|
5148
|
-
const sel =
|
|
5148
|
+
const sel = globalThis.getSelection();
|
|
5149
5149
|
if (!sel || !sel.rangeCount) return;
|
|
5150
5150
|
const r = sel.getRangeAt(0);
|
|
5151
5151
|
if (!r.collapsed) return;
|
|
@@ -5199,7 +5199,7 @@
|
|
|
5199
5199
|
/** @type {string|null} 'superscript' | 'subscript' | null */
|
|
5200
5200
|
let _compositionSupSub = null;
|
|
5201
5201
|
const onCompositionStart = () => {
|
|
5202
|
-
const sel =
|
|
5202
|
+
const sel = globalThis.getSelection();
|
|
5203
5203
|
if (!sel || !sel.rangeCount) {
|
|
5204
5204
|
_compositionSupSub = null;
|
|
5205
5205
|
return;
|
|
@@ -5217,12 +5217,12 @@
|
|
|
5217
5217
|
const tag = _compositionSupSub;
|
|
5218
5218
|
_compositionSupSub = null;
|
|
5219
5219
|
if (!tag) return;
|
|
5220
|
-
const sel =
|
|
5220
|
+
const sel = globalThis.getSelection();
|
|
5221
5221
|
if (!sel || !sel.rangeCount) return;
|
|
5222
5222
|
let node = sel.getRangeAt(0).startContainer;
|
|
5223
5223
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
5224
5224
|
const el = node;
|
|
5225
|
-
if (!(
|
|
5225
|
+
if (!(tag === "superscript" ? el?.closest("sup") : el?.closest("sub"))) document.execCommand(tag);
|
|
5226
5226
|
};
|
|
5227
5227
|
this._disposers.push(on(editable, "compositionstart", onCompositionStart), on(editable, "compositionend", onCompositionEnd));
|
|
5228
5228
|
}
|
|
@@ -5296,7 +5296,7 @@
|
|
|
5296
5296
|
if (type === "insertFromPaste" || type === "insertFromDrop") return;
|
|
5297
5297
|
if (!type.startsWith("insert")) return;
|
|
5298
5298
|
const text = this.context.layoutInfo.editable.innerText || "";
|
|
5299
|
-
const chars = text.
|
|
5299
|
+
const chars = text.replaceAll("\n", "").length;
|
|
5300
5300
|
if (maxChars && chars >= maxChars) {
|
|
5301
5301
|
event.preventDefault();
|
|
5302
5302
|
if (typeof this.options.onCharLimitReached === "function") this.options.onCharLimitReached(this.context);
|
|
@@ -5335,7 +5335,7 @@
|
|
|
5335
5335
|
*/
|
|
5336
5336
|
_cleanOrphanedFigures() {
|
|
5337
5337
|
this.context.layoutInfo.editable.querySelectorAll("figure.an-figure").forEach((fig) => {
|
|
5338
|
-
if (!fig.querySelector("img")) fig.
|
|
5338
|
+
if (!fig.querySelector("img")) fig.remove();
|
|
5339
5339
|
});
|
|
5340
5340
|
}
|
|
5341
5341
|
/**
|
|
@@ -5371,7 +5371,7 @@
|
|
|
5371
5371
|
* @returns {string}
|
|
5372
5372
|
*/
|
|
5373
5373
|
getHTML() {
|
|
5374
|
-
const raw = this.context.layoutInfo.editable.innerHTML.
|
|
5374
|
+
const raw = this.context.layoutInfo.editable.innerHTML.replaceAll("", "");
|
|
5375
5375
|
return this.context.invoke("clipboard.resolveImages", raw) ?? raw;
|
|
5376
5376
|
}
|
|
5377
5377
|
/**
|
|
@@ -5416,7 +5416,7 @@
|
|
|
5416
5416
|
* @returns {boolean}
|
|
5417
5417
|
*/
|
|
5418
5418
|
isEmpty() {
|
|
5419
|
-
const text = (this.context.layoutInfo.editable.innerText || "").trim().
|
|
5419
|
+
const text = (this.context.layoutInfo.editable.innerText || "").trim().replaceAll("\xA0", "");
|
|
5420
5420
|
const hasMedia = !!this.context.layoutInfo.editable.querySelector("img, video, iframe, table");
|
|
5421
5421
|
return !text && !hasMedia;
|
|
5422
5422
|
}
|
|
@@ -5551,11 +5551,11 @@
|
|
|
5551
5551
|
formatBlock(tagName) {
|
|
5552
5552
|
formatBlock(tagName);
|
|
5553
5553
|
if (tagName === "pre") {
|
|
5554
|
-
const sel =
|
|
5554
|
+
const sel = globalThis.getSelection();
|
|
5555
5555
|
if (sel && sel.rangeCount > 0) {
|
|
5556
5556
|
const container = sel.getRangeAt(0).commonAncestorContainer;
|
|
5557
5557
|
const pre = container.nodeType === 1 ? container.closest("pre") : container.parentElement?.closest("pre");
|
|
5558
|
-
if (pre && !pre.
|
|
5558
|
+
if (pre && !pre.dataset.language) {
|
|
5559
5559
|
const lang = detectLang(pre.textContent || "");
|
|
5560
5560
|
if (lang) {
|
|
5561
5561
|
this.context.invoke("codeTooltip.applyLanguage", pre, lang);
|
|
@@ -5608,7 +5608,7 @@
|
|
|
5608
5608
|
* @param {boolean} [openInNewTab=false]
|
|
5609
5609
|
*/
|
|
5610
5610
|
insertLink(url, text, openInNewTab = false) {
|
|
5611
|
-
const sel =
|
|
5611
|
+
const sel = globalThis.getSelection();
|
|
5612
5612
|
if (!sel || sel.rangeCount === 0) return;
|
|
5613
5613
|
const safeUrl = sanitiseUrl(url);
|
|
5614
5614
|
if (!safeUrl) return;
|
|
@@ -5671,7 +5671,7 @@
|
|
|
5671
5671
|
this.afterCommand();
|
|
5672
5672
|
}
|
|
5673
5673
|
_getClosestAnchor() {
|
|
5674
|
-
const sel =
|
|
5674
|
+
const sel = globalThis.getSelection();
|
|
5675
5675
|
if (!sel || sel.rangeCount === 0) return null;
|
|
5676
5676
|
let node = sel.getRangeAt(0).startContainer;
|
|
5677
5677
|
while (node) {
|
|
@@ -5686,7 +5686,7 @@
|
|
|
5686
5686
|
* @returns {string}
|
|
5687
5687
|
*/
|
|
5688
5688
|
_escapeAttr(str) {
|
|
5689
|
-
return String(str ?? "").
|
|
5689
|
+
return String(str ?? "").replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">");
|
|
5690
5690
|
}
|
|
5691
5691
|
};
|
|
5692
5692
|
//#endregion
|
|
@@ -5801,7 +5801,7 @@
|
|
|
5801
5801
|
this._refreshRaf = null;
|
|
5802
5802
|
this._disposers.forEach((d) => d());
|
|
5803
5803
|
this._disposers = [];
|
|
5804
|
-
if (this.el && this.el.parentNode) this.el.
|
|
5804
|
+
if (this.el && this.el.parentNode) this.el.remove();
|
|
5805
5805
|
this.el = null;
|
|
5806
5806
|
}
|
|
5807
5807
|
_buildButtons() {
|
|
@@ -5869,8 +5869,8 @@
|
|
|
5869
5869
|
let isOpen = false;
|
|
5870
5870
|
const setHighlight = (rows, cols) => {
|
|
5871
5871
|
cells.forEach((cell) => {
|
|
5872
|
-
const r = +cell.
|
|
5873
|
-
const c = +cell.
|
|
5872
|
+
const r = +cell.dataset.row;
|
|
5873
|
+
const c = +cell.dataset.col;
|
|
5874
5874
|
cell.classList.toggle("active", r <= rows && c <= cols);
|
|
5875
5875
|
});
|
|
5876
5876
|
label.textContent = rows && cols ? `${rows} × ${cols}` : this.context.locale.toolbar.insertTableLabel || "Insert Table";
|
|
@@ -5884,8 +5884,8 @@
|
|
|
5884
5884
|
const ph = popup.offsetHeight;
|
|
5885
5885
|
let left = rect.left;
|
|
5886
5886
|
let top = rect.bottom + 4;
|
|
5887
|
-
if (left + pw >
|
|
5888
|
-
if (top + ph >
|
|
5887
|
+
if (left + pw > globalThis.innerWidth - 8) left = Math.max(8, globalThis.innerWidth - pw - 8);
|
|
5888
|
+
if (top + ph > globalThis.innerHeight - 8) top = rect.top - ph - 4;
|
|
5889
5889
|
popup.style.left = `${left}px`;
|
|
5890
5890
|
popup.style.top = `${top}px`;
|
|
5891
5891
|
popup.style.visibility = "";
|
|
@@ -5905,14 +5905,14 @@
|
|
|
5905
5905
|
const d2 = on(grid, "mouseover", (e) => {
|
|
5906
5906
|
const cell = e.target?.closest(".an-table-cell");
|
|
5907
5907
|
if (!cell) return;
|
|
5908
|
-
setHighlight(+cell.
|
|
5908
|
+
setHighlight(+cell.dataset.row, +cell.dataset.col);
|
|
5909
5909
|
});
|
|
5910
5910
|
const d3 = on(grid, "mouseleave", () => setHighlight(0, 0));
|
|
5911
5911
|
const d4 = on(grid, "click", (e) => {
|
|
5912
5912
|
const cell = e.target?.closest(".an-table-cell");
|
|
5913
5913
|
if (!cell) return;
|
|
5914
|
-
const rows = +cell.
|
|
5915
|
-
const cols = +cell.
|
|
5914
|
+
const rows = +cell.dataset.row;
|
|
5915
|
+
const cols = +cell.dataset.col;
|
|
5916
5916
|
closePopup();
|
|
5917
5917
|
this.context.invoke("editor.focus");
|
|
5918
5918
|
def.action(this.context, rows, cols);
|
|
@@ -5921,7 +5921,7 @@
|
|
|
5921
5921
|
if (isOpen) closePopup();
|
|
5922
5922
|
});
|
|
5923
5923
|
this._disposers.push(d1, d2, d3, d4, d5, () => {
|
|
5924
|
-
if (popup.parentNode) popup.
|
|
5924
|
+
if (popup.parentNode) popup.remove();
|
|
5925
5925
|
});
|
|
5926
5926
|
wrap.appendChild(btn);
|
|
5927
5927
|
document.body.appendChild(popup);
|
|
@@ -6011,13 +6011,13 @@
|
|
|
6011
6011
|
/** @type {Range|null} saved selection range before popup opens */
|
|
6012
6012
|
let savedRange = null;
|
|
6013
6013
|
const saveSelection = () => {
|
|
6014
|
-
const sel =
|
|
6014
|
+
const sel = globalThis.getSelection();
|
|
6015
6015
|
savedRange = sel && sel.rangeCount ? sel.getRangeAt(0).cloneRange() : null;
|
|
6016
6016
|
};
|
|
6017
6017
|
const restoreSelection = () => {
|
|
6018
6018
|
if (!savedRange) return;
|
|
6019
6019
|
try {
|
|
6020
|
-
const sel =
|
|
6020
|
+
const sel = globalThis.getSelection();
|
|
6021
6021
|
if (!sel) return;
|
|
6022
6022
|
sel.removeAllRanges();
|
|
6023
6023
|
sel.addRange(savedRange);
|
|
@@ -6032,7 +6032,7 @@
|
|
|
6032
6032
|
const rect = arrowBtn.getBoundingClientRect();
|
|
6033
6033
|
const popupMinW = 184;
|
|
6034
6034
|
let left = rect.left;
|
|
6035
|
-
if (left + popupMinW >
|
|
6035
|
+
if (left + popupMinW > globalThis.innerWidth) left = rect.right - popupMinW;
|
|
6036
6036
|
popup.style.top = `${rect.bottom + 4}px`;
|
|
6037
6037
|
popup.style.left = `${Math.max(4, left)}px`;
|
|
6038
6038
|
popup.style.display = "block";
|
|
@@ -6095,9 +6095,9 @@
|
|
|
6095
6095
|
passive: true,
|
|
6096
6096
|
capture: true
|
|
6097
6097
|
});
|
|
6098
|
-
|
|
6099
|
-
this._disposers.push(d1, d2, d2b, d3, d3b, d4, d5, d6, () => document.removeEventListener("scroll", onScrollResize, { capture: true }), () =>
|
|
6100
|
-
if (popup.parentNode) popup.
|
|
6098
|
+
globalThis.addEventListener("resize", onScrollResize, { passive: true });
|
|
6099
|
+
this._disposers.push(d1, d2, d2b, d3, d3b, d4, d5, d6, () => document.removeEventListener("scroll", onScrollResize, { capture: true }), () => globalThis.removeEventListener("resize", onScrollResize), () => {
|
|
6100
|
+
if (popup.parentNode) popup.remove();
|
|
6101
6101
|
});
|
|
6102
6102
|
this._colorPickerClosers.push(closePopup);
|
|
6103
6103
|
this._disposers.push(() => {
|
|
@@ -6141,7 +6141,7 @@
|
|
|
6141
6141
|
/** @type {Range|null} */
|
|
6142
6142
|
let _savedRange = null;
|
|
6143
6143
|
const dMousedown = on(select, "mousedown", () => {
|
|
6144
|
-
const sel =
|
|
6144
|
+
const sel = globalThis.getSelection();
|
|
6145
6145
|
_savedRange = sel && sel.rangeCount ? sel.getRangeAt(0).cloneRange() : null;
|
|
6146
6146
|
});
|
|
6147
6147
|
const disposer = on(select, "change", (e) => {
|
|
@@ -6150,7 +6150,7 @@
|
|
|
6150
6150
|
if (!value || selectedOpt.disabled) return;
|
|
6151
6151
|
this.context.invoke("editor.focus");
|
|
6152
6152
|
if (_savedRange) try {
|
|
6153
|
-
const sel =
|
|
6153
|
+
const sel = globalThis.getSelection();
|
|
6154
6154
|
if (sel) {
|
|
6155
6155
|
sel.removeAllRanges();
|
|
6156
6156
|
sel.addRange(_savedRange);
|
|
@@ -6215,13 +6215,19 @@
|
|
|
6215
6215
|
if (!this.el) return;
|
|
6216
6216
|
const btnMap = this._btnMap || /* @__PURE__ */ new Map();
|
|
6217
6217
|
this.el.querySelectorAll("button[data-btn]").forEach((btn) => {
|
|
6218
|
-
const def = btnMap.get(
|
|
6218
|
+
const def = btnMap.get(
|
|
6219
|
+
/** @type {HTMLElement} */
|
|
6220
|
+
btn.dataset.btn
|
|
6221
|
+
);
|
|
6219
6222
|
if (def && typeof def.isActive === "function") btn.classList.toggle("active", !!def.isActive(this.context));
|
|
6220
6223
|
if (def && typeof def.isDisabled === "function")
|
|
6221
6224
|
/** @type {HTMLButtonElement} */ btn.disabled = !!def.isDisabled(this.context);
|
|
6222
6225
|
});
|
|
6223
6226
|
this.el.querySelectorAll("select[data-btn]").forEach((select) => {
|
|
6224
|
-
const def = btnMap.get(
|
|
6227
|
+
const def = btnMap.get(
|
|
6228
|
+
/** @type {HTMLElement} */
|
|
6229
|
+
select.dataset.btn
|
|
6230
|
+
);
|
|
6225
6231
|
if (!def || typeof def.getValue !== "function") return;
|
|
6226
6232
|
let raw = (def.getValue(this.context) || "").replace(/["']/g, "").trim();
|
|
6227
6233
|
if (!raw) raw = this.options.defaultFontFamily || this.options.fontFamilies && this.options.fontFamilies[0] || "";
|
|
@@ -6347,7 +6353,7 @@
|
|
|
6347
6353
|
this._dragDisposers.forEach((d) => d());
|
|
6348
6354
|
this._dragDisposers = null;
|
|
6349
6355
|
}
|
|
6350
|
-
|
|
6356
|
+
this.el?.remove();
|
|
6351
6357
|
this.el = null;
|
|
6352
6358
|
}
|
|
6353
6359
|
_bindResize(handle) {
|
|
@@ -6411,7 +6417,7 @@
|
|
|
6411
6417
|
if (!this._wordCountEl || !this._charCountEl) return;
|
|
6412
6418
|
const text = this.context.layoutInfo.editable.textContent || "";
|
|
6413
6419
|
const words = _countWords(text);
|
|
6414
|
-
const chars = text.
|
|
6420
|
+
const chars = text.replaceAll("\n", "").length;
|
|
6415
6421
|
const maxWords = this.options.maxWords || 0;
|
|
6416
6422
|
const maxChars = this.options.maxChars || 0;
|
|
6417
6423
|
const LS = this.context.locale.statusbar;
|
|
@@ -6433,7 +6439,7 @@
|
|
|
6433
6439
|
* @returns {number}
|
|
6434
6440
|
*/
|
|
6435
6441
|
getCharCount() {
|
|
6436
|
-
return (this.context.layoutInfo.editable.innerText || "").
|
|
6442
|
+
return (this.context.layoutInfo.editable.innerText || "").replaceAll("\n", "").length;
|
|
6437
6443
|
}
|
|
6438
6444
|
};
|
|
6439
6445
|
//#endregion
|
|
@@ -6526,7 +6532,7 @@
|
|
|
6526
6532
|
if (el.querySelector("a, strong, em, b, i, ul, ol, li, table, img, blockquote, pre, code, h1, h2, h3, h4, h5, h6")) continue;
|
|
6527
6533
|
const parent = el.parentNode;
|
|
6528
6534
|
while (el.firstChild) parent.insertBefore(el.firstChild, el);
|
|
6529
|
-
|
|
6535
|
+
el.remove();
|
|
6530
6536
|
}
|
|
6531
6537
|
doc.querySelectorAll("*").forEach((el) => {
|
|
6532
6538
|
el.removeAttribute("class");
|
|
@@ -6568,7 +6574,7 @@
|
|
|
6568
6574
|
this._forcePlain = !!val;
|
|
6569
6575
|
}
|
|
6570
6576
|
_onPaste(event) {
|
|
6571
|
-
const clipboardData = event.clipboardData ||
|
|
6577
|
+
const clipboardData = event.clipboardData || globalThis.clipboardData;
|
|
6572
6578
|
if (!clipboardData) return;
|
|
6573
6579
|
const forcePlain = this._forcePlain;
|
|
6574
6580
|
this._forcePlain = false;
|
|
@@ -6612,7 +6618,6 @@
|
|
|
6612
6618
|
if (this.options.pasteStripAttributes) html = this._stripAttributes(html);
|
|
6613
6619
|
execCommand("insertHTML", html);
|
|
6614
6620
|
this.context.invoke("editor.afterCommand");
|
|
6615
|
-
return;
|
|
6616
6621
|
}
|
|
6617
6622
|
}
|
|
6618
6623
|
_onDragover(event) {
|
|
@@ -6644,17 +6649,17 @@
|
|
|
6644
6649
|
this.options.onImageUpload(files);
|
|
6645
6650
|
return;
|
|
6646
6651
|
}
|
|
6647
|
-
const UNSUPPORTED = [
|
|
6652
|
+
const UNSUPPORTED = new Set([
|
|
6648
6653
|
"image/tiff",
|
|
6649
6654
|
"image/x-tiff",
|
|
6650
6655
|
"image/bmp",
|
|
6651
6656
|
"image/x-bmp",
|
|
6652
6657
|
"image/x-ms-bmp"
|
|
6653
|
-
];
|
|
6658
|
+
]);
|
|
6654
6659
|
const maxBytes = (this.options.maxImageSize || 5) * 1024 * 1024;
|
|
6655
6660
|
files.forEach((file) => {
|
|
6656
6661
|
if (!file || !file.type.startsWith("image/")) return;
|
|
6657
|
-
if (UNSUPPORTED.
|
|
6662
|
+
if (UNSUPPORTED.has(file.type)) {
|
|
6658
6663
|
const message = `Image format "${file.type}" is not supported for display in web browsers. Please convert to PNG, JPEG, or WebP first.`;
|
|
6659
6664
|
this.context.triggerEvent("imageError", {
|
|
6660
6665
|
file,
|
|
@@ -6706,10 +6711,10 @@
|
|
|
6706
6711
|
*/
|
|
6707
6712
|
_dataUrlToBlob(dataUrl) {
|
|
6708
6713
|
const [header, b64] = dataUrl.split(",");
|
|
6709
|
-
const mime =
|
|
6714
|
+
const mime = /:(.*?);/.exec(header)?.[1] ?? "image/png";
|
|
6710
6715
|
const binary = atob(b64);
|
|
6711
6716
|
const arr = new Uint8Array(binary.length);
|
|
6712
|
-
for (let i = 0; i < binary.length; i++) arr[i] = binary.
|
|
6717
|
+
for (let i = 0; i < binary.length; i++) arr[i] = binary.codePointAt(i);
|
|
6713
6718
|
return new Blob([arr], { type: mime });
|
|
6714
6719
|
}
|
|
6715
6720
|
/**
|
|
@@ -6777,7 +6782,7 @@
|
|
|
6777
6782
|
}
|
|
6778
6783
|
}
|
|
6779
6784
|
if (!range) return;
|
|
6780
|
-
const sel =
|
|
6785
|
+
const sel = globalThis.getSelection();
|
|
6781
6786
|
if (sel) {
|
|
6782
6787
|
sel.removeAllRanges();
|
|
6783
6788
|
sel.addRange(range);
|
|
@@ -6789,7 +6794,7 @@
|
|
|
6789
6794
|
* @returns {string}
|
|
6790
6795
|
*/
|
|
6791
6796
|
_escapeHTML(str) {
|
|
6792
|
-
return str.
|
|
6797
|
+
return str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
6793
6798
|
}
|
|
6794
6799
|
};
|
|
6795
6800
|
//#endregion
|
|
@@ -6826,7 +6831,7 @@
|
|
|
6826
6831
|
_update() {
|
|
6827
6832
|
const editable = this.context.layoutInfo.editable;
|
|
6828
6833
|
const isFocused = document.activeElement === editable;
|
|
6829
|
-
const isEmpty = !(editable.textContent.
|
|
6834
|
+
const isEmpty = !(editable.textContent.replaceAll("", "").trim().length > 0) && !editable.querySelector("img, table, hr, .an-video-wrapper");
|
|
6830
6835
|
editable.classList.toggle("an-placeholder", isEmpty && !isFocused);
|
|
6831
6836
|
}
|
|
6832
6837
|
};
|
|
@@ -6854,7 +6859,7 @@
|
|
|
6854
6859
|
destroy() {
|
|
6855
6860
|
this._disposers.forEach((d) => d());
|
|
6856
6861
|
this._disposers = [];
|
|
6857
|
-
|
|
6862
|
+
this._textarea?.remove();
|
|
6858
6863
|
this._textarea = null;
|
|
6859
6864
|
}
|
|
6860
6865
|
toggle() {
|
|
@@ -6885,7 +6890,7 @@
|
|
|
6885
6890
|
if (!this._active || !this._textarea) return;
|
|
6886
6891
|
const { editable } = this.context.layoutInfo;
|
|
6887
6892
|
editable.innerHTML = sanitiseHTML(this._textarea.value, { allowIframes: true });
|
|
6888
|
-
this._textarea.
|
|
6893
|
+
this._textarea.remove();
|
|
6889
6894
|
this._textarea = null;
|
|
6890
6895
|
editable.style.display = "";
|
|
6891
6896
|
this._active = false;
|
|
@@ -6909,7 +6914,7 @@
|
|
|
6909
6914
|
}).split("\n").map((line) => {
|
|
6910
6915
|
const stripped = line.trim();
|
|
6911
6916
|
if (!stripped) return "";
|
|
6912
|
-
if (
|
|
6917
|
+
if (stripped.startsWith("</")) indent = Math.max(0, indent - 1);
|
|
6913
6918
|
const out = " ".repeat(indent) + stripped;
|
|
6914
6919
|
if (/^<[^/!][^>]*[^/]>/.test(stripped) && !INLINE_RE.test(stripped) && !/^<(br|hr|img|input|link|meta)/.test(stripped)) indent++;
|
|
6915
6920
|
return out;
|
|
@@ -6973,15 +6978,13 @@
|
|
|
6973
6978
|
}
|
|
6974
6979
|
};
|
|
6975
6980
|
//#endregion
|
|
6976
|
-
//#region src/js/module/
|
|
6981
|
+
//#region src/js/module/BaseDialog.js
|
|
6977
6982
|
/**
|
|
6978
|
-
*
|
|
6979
|
-
*
|
|
6983
|
+
* Shared lifecycle and shell-building logic for all modal dialogs.
|
|
6984
|
+
* Subclasses implement _buildDialog() for their specific form fields.
|
|
6980
6985
|
*/
|
|
6981
|
-
var
|
|
6982
|
-
/**
|
|
6983
|
-
* @param {import('../Context.js').Context} context
|
|
6984
|
-
*/
|
|
6986
|
+
var BaseDialog = class {
|
|
6987
|
+
/** @param {import('../Context.js').Context} context */
|
|
6985
6988
|
constructor(context) {
|
|
6986
6989
|
this.context = context;
|
|
6987
6990
|
this.options = context.options;
|
|
@@ -6989,6 +6992,9 @@
|
|
|
6989
6992
|
this._dialog = null;
|
|
6990
6993
|
this._disposers = [];
|
|
6991
6994
|
this._savedRange = null;
|
|
6995
|
+
/** @type {HTMLElement|null} First focusable input; set by subclass in _buildDialog(). */
|
|
6996
|
+
this._firstInput = null;
|
|
6997
|
+
this._removeTrap = null;
|
|
6992
6998
|
}
|
|
6993
6999
|
initialize() {
|
|
6994
7000
|
this._dialog = this._buildDialog();
|
|
@@ -6998,36 +7004,113 @@
|
|
|
6998
7004
|
destroy() {
|
|
6999
7005
|
this._disposers.forEach((d) => d());
|
|
7000
7006
|
this._disposers = [];
|
|
7001
|
-
if (this._dialog
|
|
7007
|
+
if (this._dialog?.parentNode) this._dialog.remove();
|
|
7002
7008
|
this._dialog = null;
|
|
7003
7009
|
}
|
|
7004
|
-
/**
|
|
7005
|
-
|
|
7006
|
-
* Pre-fills with the currently selected link if present.
|
|
7007
|
-
*/
|
|
7008
|
-
show() {
|
|
7010
|
+
/** Saves the current selection range before opening the dialog. */
|
|
7011
|
+
_saveRange() {
|
|
7009
7012
|
withSavedRange((range) => {
|
|
7010
7013
|
this._savedRange = range;
|
|
7011
7014
|
});
|
|
7012
|
-
this._prefill();
|
|
7013
|
-
this._open();
|
|
7014
7015
|
}
|
|
7015
|
-
|
|
7016
|
-
|
|
7016
|
+
_open() {
|
|
7017
|
+
if (this._dialog) {
|
|
7018
|
+
this._dialog.style.display = "flex";
|
|
7019
|
+
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7020
|
+
setTimeout(() => this._firstInput && this._firstInput.focus(), 50);
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
7023
|
+
_close() {
|
|
7024
|
+
if (this._dialog) this._dialog.style.display = "none";
|
|
7025
|
+
if (this._removeTrap) {
|
|
7026
|
+
this._removeTrap();
|
|
7027
|
+
this._removeTrap = null;
|
|
7028
|
+
}
|
|
7029
|
+
this._savedRange = null;
|
|
7030
|
+
}
|
|
7031
|
+
/**
|
|
7032
|
+
* Builds the overlay + box + header shell common to all dialogs.
|
|
7033
|
+
* Also wires up draggable and overlay-click-to-close.
|
|
7034
|
+
* @param {string} ariaLabel
|
|
7035
|
+
* @param {string} iconHtml Raw SVG string for the dialog icon
|
|
7036
|
+
* @param {string} titleText
|
|
7037
|
+
* @returns {{ overlay: HTMLElement, box: HTMLElement }}
|
|
7038
|
+
*/
|
|
7039
|
+
_buildDialogShell(ariaLabel, iconHtml, titleText) {
|
|
7017
7040
|
const overlay = createElement("div", {
|
|
7018
7041
|
class: "an-dialog-overlay",
|
|
7019
7042
|
role: "dialog",
|
|
7020
7043
|
"aria-modal": "true",
|
|
7021
|
-
"aria-label":
|
|
7044
|
+
"aria-label": ariaLabel
|
|
7022
7045
|
});
|
|
7023
7046
|
const box = createElement("div", { class: "an-dialog-box" });
|
|
7024
7047
|
const header = createElement("div", { class: "an-dialog-header" });
|
|
7025
7048
|
const iconEl = createElement("span", { class: "an-dialog-icon" });
|
|
7026
|
-
iconEl.innerHTML =
|
|
7027
|
-
const
|
|
7028
|
-
|
|
7049
|
+
iconEl.innerHTML = iconHtml;
|
|
7050
|
+
const titleEl = createElement("h3", { class: "an-dialog-title" });
|
|
7051
|
+
titleEl.textContent = titleText;
|
|
7029
7052
|
header.appendChild(iconEl);
|
|
7030
|
-
header.appendChild(
|
|
7053
|
+
header.appendChild(titleEl);
|
|
7054
|
+
box.appendChild(header);
|
|
7055
|
+
overlay.appendChild(box);
|
|
7056
|
+
makeDraggable(header, box);
|
|
7057
|
+
const d = on(overlay, "click", (e) => {
|
|
7058
|
+
if (e.target === overlay) this._close();
|
|
7059
|
+
});
|
|
7060
|
+
this._disposers.push(d);
|
|
7061
|
+
return {
|
|
7062
|
+
overlay,
|
|
7063
|
+
box
|
|
7064
|
+
};
|
|
7065
|
+
}
|
|
7066
|
+
/**
|
|
7067
|
+
* Builds an action button row with a primary insert button and a cancel button.
|
|
7068
|
+
* Disposers are registered automatically.
|
|
7069
|
+
* @param {string} insertLabel
|
|
7070
|
+
* @param {string} cancelLabel
|
|
7071
|
+
* @param {() => void} onInsert
|
|
7072
|
+
* @returns {HTMLElement}
|
|
7073
|
+
*/
|
|
7074
|
+
_buildButtonRow(insertLabel, cancelLabel, onInsert) {
|
|
7075
|
+
const btnRow = createElement("div", { class: "an-dialog-actions" });
|
|
7076
|
+
const insertBtn = createElement("button", {
|
|
7077
|
+
type: "button",
|
|
7078
|
+
class: "an-btn an-btn-primary"
|
|
7079
|
+
});
|
|
7080
|
+
insertBtn.textContent = insertLabel;
|
|
7081
|
+
const cancelBtn = createElement("button", {
|
|
7082
|
+
type: "button",
|
|
7083
|
+
class: "an-btn"
|
|
7084
|
+
});
|
|
7085
|
+
cancelBtn.textContent = cancelLabel;
|
|
7086
|
+
btnRow.appendChild(insertBtn);
|
|
7087
|
+
btnRow.appendChild(cancelBtn);
|
|
7088
|
+
const d1 = on(insertBtn, "click", onInsert);
|
|
7089
|
+
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7090
|
+
this._disposers.push(d1, d2);
|
|
7091
|
+
return btnRow;
|
|
7092
|
+
}
|
|
7093
|
+
};
|
|
7094
|
+
//#endregion
|
|
7095
|
+
//#region src/js/module/LinkDialog.js
|
|
7096
|
+
/**
|
|
7097
|
+
* LinkDialog.js - Dialog for inserting / editing hyperlinks
|
|
7098
|
+
* Inspired by Summernote's LinkDialog — rewritten without jQuery
|
|
7099
|
+
*/
|
|
7100
|
+
var ICON_SVG$2 = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>`;
|
|
7101
|
+
var LinkDialog = class extends BaseDialog {
|
|
7102
|
+
/**
|
|
7103
|
+
* Opens the link dialog.
|
|
7104
|
+
* Pre-fills with the currently selected link if present.
|
|
7105
|
+
*/
|
|
7106
|
+
show() {
|
|
7107
|
+
this._saveRange();
|
|
7108
|
+
this._prefill();
|
|
7109
|
+
this._open();
|
|
7110
|
+
}
|
|
7111
|
+
_buildDialog() {
|
|
7112
|
+
const L = this.context.locale.linkDialog;
|
|
7113
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG$2, L.title);
|
|
7031
7114
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
7032
7115
|
urlLabel.textContent = L.url;
|
|
7033
7116
|
const urlInput = createElement("input", {
|
|
@@ -7039,6 +7122,7 @@
|
|
|
7039
7122
|
autocomplete: "off"
|
|
7040
7123
|
});
|
|
7041
7124
|
this._urlInput = urlInput;
|
|
7125
|
+
this._firstInput = urlInput;
|
|
7042
7126
|
const textLabel = createElement("label", { class: "an-label" });
|
|
7043
7127
|
textLabel.textContent = L.displayText;
|
|
7044
7128
|
const textInput = createElement("input", {
|
|
@@ -7059,27 +7143,8 @@
|
|
|
7059
7143
|
this._tabCheckbox = tabCheckbox;
|
|
7060
7144
|
tabLabel.appendChild(tabCheckbox);
|
|
7061
7145
|
tabLabel.appendChild(document.createTextNode(" " + L.openInNewTab));
|
|
7062
|
-
const btnRow =
|
|
7063
|
-
|
|
7064
|
-
type: "button",
|
|
7065
|
-
class: "an-btn an-btn-primary"
|
|
7066
|
-
});
|
|
7067
|
-
insertBtn.textContent = L.insertBtn;
|
|
7068
|
-
const cancelBtn = createElement("button", {
|
|
7069
|
-
type: "button",
|
|
7070
|
-
class: "an-btn"
|
|
7071
|
-
});
|
|
7072
|
-
cancelBtn.textContent = L.cancelBtn;
|
|
7073
|
-
btnRow.appendChild(insertBtn);
|
|
7074
|
-
btnRow.appendChild(cancelBtn);
|
|
7075
|
-
box.append(header, urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);
|
|
7076
|
-
overlay.appendChild(box);
|
|
7077
|
-
makeDraggable(header, box);
|
|
7078
|
-
const d1 = on(insertBtn, "click", () => this._onInsert());
|
|
7079
|
-
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7080
|
-
const d3 = on(overlay, "click", (e) => {
|
|
7081
|
-
if (e.target === overlay) this._close();
|
|
7082
|
-
});
|
|
7146
|
+
const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());
|
|
7147
|
+
box.append(urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);
|
|
7083
7148
|
const d4 = on(urlInput, "keydown", (e) => {
|
|
7084
7149
|
if (e.key === "Enter") {
|
|
7085
7150
|
e.preventDefault();
|
|
@@ -7092,11 +7157,11 @@
|
|
|
7092
7157
|
this._onInsert();
|
|
7093
7158
|
}
|
|
7094
7159
|
});
|
|
7095
|
-
this._disposers.push(
|
|
7160
|
+
this._disposers.push(d4, d5);
|
|
7096
7161
|
return overlay;
|
|
7097
7162
|
}
|
|
7098
7163
|
_prefill() {
|
|
7099
|
-
const sel =
|
|
7164
|
+
const sel = globalThis.getSelection();
|
|
7100
7165
|
let anchor = null;
|
|
7101
7166
|
if (sel && sel.rangeCount > 0) {
|
|
7102
7167
|
let node = sel.getRangeAt(0).startContainer;
|
|
@@ -7141,21 +7206,6 @@
|
|
|
7141
7206
|
this.context.invoke("editor.insertLink", url, text, newTab);
|
|
7142
7207
|
this._close();
|
|
7143
7208
|
}
|
|
7144
|
-
_open() {
|
|
7145
|
-
if (this._dialog) {
|
|
7146
|
-
this._dialog.style.display = "flex";
|
|
7147
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7148
|
-
setTimeout(() => this._urlInput && this._urlInput.focus(), 50);
|
|
7149
|
-
}
|
|
7150
|
-
}
|
|
7151
|
-
_close() {
|
|
7152
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
7153
|
-
if (this._removeTrap) {
|
|
7154
|
-
this._removeTrap();
|
|
7155
|
-
this._removeTrap = null;
|
|
7156
|
-
}
|
|
7157
|
-
this._savedRange = null;
|
|
7158
|
-
}
|
|
7159
7209
|
};
|
|
7160
7210
|
//#endregion
|
|
7161
7211
|
//#region src/js/module/ImageDialog.js
|
|
@@ -7163,33 +7213,10 @@
|
|
|
7163
7213
|
* ImageDialog.js - Dialog for inserting images (by URL or file upload)
|
|
7164
7214
|
* Inspired by Summernote's ImageDialog — rewritten without jQuery
|
|
7165
7215
|
*/
|
|
7166
|
-
var
|
|
7167
|
-
|
|
7168
|
-
* @param {import('../Context.js').Context} context
|
|
7169
|
-
*/
|
|
7170
|
-
constructor(context) {
|
|
7171
|
-
this.context = context;
|
|
7172
|
-
this.options = context.options;
|
|
7173
|
-
/** @type {HTMLElement|null} */
|
|
7174
|
-
this._dialog = null;
|
|
7175
|
-
this._disposers = [];
|
|
7176
|
-
this._savedRange = null;
|
|
7177
|
-
}
|
|
7178
|
-
initialize() {
|
|
7179
|
-
this._dialog = this._buildDialog();
|
|
7180
|
-
document.body.appendChild(this._dialog);
|
|
7181
|
-
return this;
|
|
7182
|
-
}
|
|
7183
|
-
destroy() {
|
|
7184
|
-
this._disposers.forEach((d) => d());
|
|
7185
|
-
this._disposers = [];
|
|
7186
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.parentNode.removeChild(this._dialog);
|
|
7187
|
-
this._dialog = null;
|
|
7188
|
-
}
|
|
7216
|
+
var ICON_SVG$1 = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
7217
|
+
var ImageDialog = class extends BaseDialog {
|
|
7189
7218
|
show() {
|
|
7190
|
-
|
|
7191
|
-
this._savedRange = range;
|
|
7192
|
-
});
|
|
7219
|
+
this._saveRange();
|
|
7193
7220
|
this._urlInput.value = "";
|
|
7194
7221
|
this._altInput.value = "";
|
|
7195
7222
|
if (this._fileInput) this._fileInput.value = "";
|
|
@@ -7197,20 +7224,7 @@
|
|
|
7197
7224
|
}
|
|
7198
7225
|
_buildDialog() {
|
|
7199
7226
|
const L = this.context.locale.imageDialog;
|
|
7200
|
-
const overlay =
|
|
7201
|
-
class: "an-dialog-overlay",
|
|
7202
|
-
role: "dialog",
|
|
7203
|
-
"aria-modal": "true",
|
|
7204
|
-
"aria-label": L.ariaLabel
|
|
7205
|
-
});
|
|
7206
|
-
const box = createElement("div", { class: "an-dialog-box" });
|
|
7207
|
-
const header = createElement("div", { class: "an-dialog-header" });
|
|
7208
|
-
const iconEl = createElement("span", { class: "an-dialog-icon" });
|
|
7209
|
-
iconEl.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
7210
|
-
const title = createElement("h3", { class: "an-dialog-title" });
|
|
7211
|
-
title.textContent = L.title;
|
|
7212
|
-
header.appendChild(iconEl);
|
|
7213
|
-
header.appendChild(title);
|
|
7227
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG$1, L.title);
|
|
7214
7228
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
7215
7229
|
urlLabel.textContent = L.imageUrl;
|
|
7216
7230
|
const urlInput = createElement("input", {
|
|
@@ -7220,6 +7234,7 @@
|
|
|
7220
7234
|
autocomplete: "off"
|
|
7221
7235
|
});
|
|
7222
7236
|
this._urlInput = urlInput;
|
|
7237
|
+
this._firstInput = urlInput;
|
|
7223
7238
|
const altLabel = createElement("label", { class: "an-label" });
|
|
7224
7239
|
altLabel.textContent = L.altText;
|
|
7225
7240
|
const altInput = createElement("input", {
|
|
@@ -7229,7 +7244,7 @@
|
|
|
7229
7244
|
autocomplete: "off"
|
|
7230
7245
|
});
|
|
7231
7246
|
this._altInput = altInput;
|
|
7232
|
-
box.append(
|
|
7247
|
+
box.append(urlLabel, urlInput, altLabel, altInput);
|
|
7233
7248
|
const alignLabel = createElement("label", { class: "an-label" });
|
|
7234
7249
|
alignLabel.textContent = L.alignment;
|
|
7235
7250
|
const alignRow = createElement("div", { class: "an-align-row" });
|
|
@@ -7283,27 +7298,8 @@
|
|
|
7283
7298
|
this._disposers.push(d);
|
|
7284
7299
|
box.append(fileLabel, fileInput, fileHint);
|
|
7285
7300
|
}
|
|
7286
|
-
const btnRow =
|
|
7287
|
-
const insertBtn = createElement("button", {
|
|
7288
|
-
type: "button",
|
|
7289
|
-
class: "an-btn an-btn-primary"
|
|
7290
|
-
});
|
|
7291
|
-
insertBtn.textContent = L.insertBtn;
|
|
7292
|
-
const cancelBtn = createElement("button", {
|
|
7293
|
-
type: "button",
|
|
7294
|
-
class: "an-btn"
|
|
7295
|
-
});
|
|
7296
|
-
cancelBtn.textContent = L.cancelBtn;
|
|
7297
|
-
btnRow.appendChild(insertBtn);
|
|
7298
|
-
btnRow.appendChild(cancelBtn);
|
|
7301
|
+
const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());
|
|
7299
7302
|
box.append(btnRow);
|
|
7300
|
-
overlay.appendChild(box);
|
|
7301
|
-
makeDraggable(header, box);
|
|
7302
|
-
const d1 = on(insertBtn, "click", () => this._onInsert());
|
|
7303
|
-
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7304
|
-
const d3 = on(overlay, "click", (e) => {
|
|
7305
|
-
if (e.target === overlay) this._close();
|
|
7306
|
-
});
|
|
7307
7303
|
const d4 = on(urlInput, "keydown", (e) => {
|
|
7308
7304
|
if (e.key === "Enter") {
|
|
7309
7305
|
e.preventDefault();
|
|
@@ -7316,7 +7312,7 @@
|
|
|
7316
7312
|
this._onInsert();
|
|
7317
7313
|
}
|
|
7318
7314
|
});
|
|
7319
|
-
this._disposers.push(
|
|
7315
|
+
this._disposers.push(d4, d5);
|
|
7320
7316
|
return overlay;
|
|
7321
7317
|
}
|
|
7322
7318
|
_onFileChange() {
|
|
@@ -7371,21 +7367,6 @@
|
|
|
7371
7367
|
this.context.invoke("editor.insertImage", src, alt, align);
|
|
7372
7368
|
this._close();
|
|
7373
7369
|
}
|
|
7374
|
-
_open() {
|
|
7375
|
-
if (this._dialog) {
|
|
7376
|
-
this._dialog.style.display = "flex";
|
|
7377
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7378
|
-
setTimeout(() => this._urlInput && this._urlInput.focus(), 50);
|
|
7379
|
-
}
|
|
7380
|
-
}
|
|
7381
|
-
_close() {
|
|
7382
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
7383
|
-
if (this._removeTrap) {
|
|
7384
|
-
this._removeTrap();
|
|
7385
|
-
this._removeTrap = null;
|
|
7386
|
-
}
|
|
7387
|
-
this._savedRange = null;
|
|
7388
|
-
}
|
|
7389
7370
|
};
|
|
7390
7371
|
//#endregion
|
|
7391
7372
|
//#region src/js/module/VideoDialog.js
|
|
@@ -7397,31 +7378,10 @@
|
|
|
7397
7378
|
* • Vimeo URLs → <iframe> embed
|
|
7398
7379
|
* • Direct video URLs → <video> element (.mp4 / .webm / .ogg)
|
|
7399
7380
|
*/
|
|
7400
|
-
var
|
|
7401
|
-
|
|
7402
|
-
constructor(context) {
|
|
7403
|
-
this.context = context;
|
|
7404
|
-
this.options = context.options;
|
|
7405
|
-
/** @type {HTMLElement|null} */
|
|
7406
|
-
this._dialog = null;
|
|
7407
|
-
this._disposers = [];
|
|
7408
|
-
this._savedRange = null;
|
|
7409
|
-
}
|
|
7410
|
-
initialize() {
|
|
7411
|
-
this._dialog = this._buildDialog();
|
|
7412
|
-
document.body.appendChild(this._dialog);
|
|
7413
|
-
return this;
|
|
7414
|
-
}
|
|
7415
|
-
destroy() {
|
|
7416
|
-
this._disposers.forEach((d) => d());
|
|
7417
|
-
this._disposers = [];
|
|
7418
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.parentNode.removeChild(this._dialog);
|
|
7419
|
-
this._dialog = null;
|
|
7420
|
-
}
|
|
7381
|
+
var ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2"/></svg>`;
|
|
7382
|
+
var VideoDialog = class extends BaseDialog {
|
|
7421
7383
|
show() {
|
|
7422
|
-
|
|
7423
|
-
this._savedRange = range;
|
|
7424
|
-
});
|
|
7384
|
+
this._saveRange();
|
|
7425
7385
|
this._urlInput.value = "";
|
|
7426
7386
|
this._widthInput.value = "560";
|
|
7427
7387
|
this._hintEl.textContent = "";
|
|
@@ -7429,20 +7389,7 @@
|
|
|
7429
7389
|
}
|
|
7430
7390
|
_buildDialog() {
|
|
7431
7391
|
const L = this.context.locale.videoDialog;
|
|
7432
|
-
const overlay =
|
|
7433
|
-
class: "an-dialog-overlay",
|
|
7434
|
-
role: "dialog",
|
|
7435
|
-
"aria-modal": "true",
|
|
7436
|
-
"aria-label": L.ariaLabel
|
|
7437
|
-
});
|
|
7438
|
-
const box = createElement("div", { class: "an-dialog-box" });
|
|
7439
|
-
const header = createElement("div", { class: "an-dialog-header" });
|
|
7440
|
-
const iconEl = createElement("span", { class: "an-dialog-icon" });
|
|
7441
|
-
iconEl.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2"/></svg>`;
|
|
7442
|
-
const title = createElement("h3", { class: "an-dialog-title" });
|
|
7443
|
-
title.textContent = L.title;
|
|
7444
|
-
header.appendChild(iconEl);
|
|
7445
|
-
header.appendChild(title);
|
|
7392
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);
|
|
7446
7393
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
7447
7394
|
urlLabel.textContent = L.videoUrl;
|
|
7448
7395
|
const urlInput = createElement("input", {
|
|
@@ -7452,6 +7399,7 @@
|
|
|
7452
7399
|
autocomplete: "off"
|
|
7453
7400
|
});
|
|
7454
7401
|
this._urlInput = urlInput;
|
|
7402
|
+
this._firstInput = urlInput;
|
|
7455
7403
|
const hintEl = createElement("p", { class: "an-dialog-hint" });
|
|
7456
7404
|
this._hintEl = hintEl;
|
|
7457
7405
|
const widthLabel = createElement("label", { class: "an-label" });
|
|
@@ -7465,43 +7413,24 @@
|
|
|
7465
7413
|
value: "560"
|
|
7466
7414
|
});
|
|
7467
7415
|
this._widthInput = widthInput;
|
|
7468
|
-
const btnRow =
|
|
7469
|
-
|
|
7470
|
-
type: "button",
|
|
7471
|
-
class: "an-btn an-btn-primary"
|
|
7472
|
-
});
|
|
7473
|
-
insertBtn.textContent = L.insertBtn;
|
|
7474
|
-
const cancelBtn = createElement("button", {
|
|
7475
|
-
type: "button",
|
|
7476
|
-
class: "an-btn"
|
|
7477
|
-
});
|
|
7478
|
-
cancelBtn.textContent = L.cancelBtn;
|
|
7479
|
-
btnRow.appendChild(insertBtn);
|
|
7480
|
-
btnRow.appendChild(cancelBtn);
|
|
7481
|
-
box.append(header, urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);
|
|
7482
|
-
overlay.appendChild(box);
|
|
7483
|
-
makeDraggable(header, box);
|
|
7416
|
+
const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());
|
|
7417
|
+
box.append(urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);
|
|
7484
7418
|
const d0 = on(urlInput, "input", () => {
|
|
7485
7419
|
const info = this._parseVideoUrl(urlInput.value.trim());
|
|
7486
7420
|
hintEl.textContent = info ? this.context.locale.videoDialog.detected(info.type) : urlInput.value ? this.context.locale.videoDialog.unknownFormat : "";
|
|
7487
7421
|
});
|
|
7488
|
-
const d1 = on(insertBtn, "click", () => this._onInsert());
|
|
7489
|
-
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7490
|
-
const d3 = on(overlay, "click", (e) => {
|
|
7491
|
-
if (e.target === overlay) this._close();
|
|
7492
|
-
});
|
|
7493
7422
|
const d4 = on(urlInput, "keydown", (e) => {
|
|
7494
7423
|
if (e.key === "Enter") {
|
|
7495
7424
|
e.preventDefault();
|
|
7496
7425
|
this._onInsert();
|
|
7497
7426
|
}
|
|
7498
7427
|
});
|
|
7499
|
-
this._disposers.push(d0,
|
|
7428
|
+
this._disposers.push(d0, d4);
|
|
7500
7429
|
return overlay;
|
|
7501
7430
|
}
|
|
7502
7431
|
_onInsert() {
|
|
7503
7432
|
const rawUrl = this._urlInput.value.trim();
|
|
7504
|
-
const width = Math.max(80, parseInt(this._widthInput.value, 10) || 560);
|
|
7433
|
+
const width = Math.max(80, Number.parseInt(this._widthInput.value, 10) || 560);
|
|
7505
7434
|
if (!rawUrl) {
|
|
7506
7435
|
this._urlInput.focus();
|
|
7507
7436
|
return;
|
|
@@ -7516,21 +7445,6 @@
|
|
|
7516
7445
|
this.context.invoke("editor.insertVideo", html);
|
|
7517
7446
|
this._close();
|
|
7518
7447
|
}
|
|
7519
|
-
_open() {
|
|
7520
|
-
if (this._dialog) {
|
|
7521
|
-
this._dialog.style.display = "flex";
|
|
7522
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7523
|
-
setTimeout(() => this._urlInput && this._urlInput.focus(), 50);
|
|
7524
|
-
}
|
|
7525
|
-
}
|
|
7526
|
-
_close() {
|
|
7527
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
7528
|
-
if (this._removeTrap) {
|
|
7529
|
-
this._removeTrap();
|
|
7530
|
-
this._removeTrap = null;
|
|
7531
|
-
}
|
|
7532
|
-
this._savedRange = null;
|
|
7533
|
-
}
|
|
7534
7448
|
/**
|
|
7535
7449
|
* Parses a video URL and returns { type, embedUrl } or null.
|
|
7536
7450
|
* @param {string} url
|
|
@@ -7544,22 +7458,22 @@
|
|
|
7544
7458
|
} catch {
|
|
7545
7459
|
return null;
|
|
7546
7460
|
}
|
|
7547
|
-
const ytWatch =
|
|
7461
|
+
const ytWatch = /(?:youtube\.com\/watch\?(?:.*&)?v=|youtube\.com\/embed\/)([a-zA-Z0-9_-]{11})/.exec(url);
|
|
7548
7462
|
if (ytWatch) return {
|
|
7549
7463
|
type: "YouTube",
|
|
7550
7464
|
embedUrl: `https://www.youtube.com/embed/${ytWatch[1]}`
|
|
7551
7465
|
};
|
|
7552
|
-
const ytShort =
|
|
7466
|
+
const ytShort = /youtu\.be\/([a-zA-Z0-9_-]{11})/.exec(url);
|
|
7553
7467
|
if (ytShort) return {
|
|
7554
7468
|
type: "YouTube",
|
|
7555
7469
|
embedUrl: `https://www.youtube.com/embed/${ytShort[1]}`
|
|
7556
7470
|
};
|
|
7557
|
-
const ytShorts =
|
|
7471
|
+
const ytShorts = /youtube\.com\/shorts\/([a-zA-Z0-9_-]{11})/.exec(url);
|
|
7558
7472
|
if (ytShorts) return {
|
|
7559
7473
|
type: "YouTube Shorts",
|
|
7560
7474
|
embedUrl: `https://www.youtube.com/embed/${ytShorts[1]}`
|
|
7561
7475
|
};
|
|
7562
|
-
const vimeo =
|
|
7476
|
+
const vimeo = /vimeo\.com\/(\d+)/.exec(url);
|
|
7563
7477
|
if (vimeo) return {
|
|
7564
7478
|
type: "Vimeo",
|
|
7565
7479
|
embedUrl: `https://player.vimeo.com/video/${vimeo[1]}`
|
|
@@ -7583,7 +7497,7 @@
|
|
|
7583
7497
|
const iframeTitle = `${info.type} video player`;
|
|
7584
7498
|
return `<div class="an-video-wrapper" style="position:relative;display:block;width:${width}px;max-width:100%"><iframe src="${info.embedUrl}" width="${width}" height="${height}" title="${iframeTitle}" frameborder="0" allowfullscreen allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" style="display:block;max-width:100%"></iframe><div class="an-video-shield"></div></div>`;
|
|
7585
7499
|
}
|
|
7586
|
-
if (info && info.type === "Direct video") return `<div class="an-video-wrapper" style="position:relative;display:block;width:${width}px;max-width:100%"><video src="${info.embedUrl.
|
|
7500
|
+
if (info && info.type === "Direct video") return `<div class="an-video-wrapper" style="position:relative;display:block;width:${width}px;max-width:100%"><video src="${info.embedUrl.replaceAll("\"", "%22")}" width="${width}" height="${height}" controls style="display:block;max-width:100%"></video><div class="an-video-shield"></div></div>`;
|
|
7587
7501
|
const safeSrc = (() => {
|
|
7588
7502
|
try {
|
|
7589
7503
|
const p = new URL(url);
|
|
@@ -7594,7 +7508,7 @@
|
|
|
7594
7508
|
}
|
|
7595
7509
|
})();
|
|
7596
7510
|
if (!safeSrc) return null;
|
|
7597
|
-
return `<div class="an-video-wrapper" style="position:relative;display:block;width:${width}px;max-width:100%"><video src="${safeSrc.
|
|
7511
|
+
return `<div class="an-video-wrapper" style="position:relative;display:block;width:${width}px;max-width:100%"><video src="${safeSrc.replaceAll("\"", "%22")}" width="${width}" height="${height}" controls style="display:block;max-width:100%"></video><div class="an-video-shield"></div></div>`;
|
|
7598
7512
|
}
|
|
7599
7513
|
};
|
|
7600
7514
|
//#endregion
|
|
@@ -7665,7 +7579,7 @@
|
|
|
7665
7579
|
if (this.context.layoutInfo.container.classList.contains("an-disabled")) return;
|
|
7666
7580
|
const img = e.target?.closest("img");
|
|
7667
7581
|
if (img) this._select(img);
|
|
7668
|
-
}), on(document, "click", (e) => this._onDocClick(e)), on(
|
|
7582
|
+
}), on(document, "click", (e) => this._onDocClick(e)), on(globalThis, "scroll", () => this._updateOverlayPosition(), { passive: true }), on(globalThis, "resize", onWindowResize, { passive: true }), on(editable, "scroll", () => this._updateOverlayPosition(), { passive: true }));
|
|
7669
7583
|
return this;
|
|
7670
7584
|
}
|
|
7671
7585
|
destroy() {
|
|
@@ -7680,7 +7594,7 @@
|
|
|
7680
7594
|
this._positionRaf = null;
|
|
7681
7595
|
}
|
|
7682
7596
|
this._deselect();
|
|
7683
|
-
if (this._overlay && this._overlay.parentNode) this._overlay.
|
|
7597
|
+
if (this._overlay && this._overlay.parentNode) this._overlay.remove();
|
|
7684
7598
|
this._overlay = null;
|
|
7685
7599
|
}
|
|
7686
7600
|
/** @returns {HTMLImageElement|null} */
|
|
@@ -7882,7 +7796,7 @@
|
|
|
7882
7796
|
if (this.context.layoutInfo.container.classList.contains("an-disabled")) return;
|
|
7883
7797
|
const wrapper = this._findWrapper(e.target);
|
|
7884
7798
|
if (wrapper) this._select(wrapper);
|
|
7885
|
-
}), on(document, "click", (e) => this._onDocClick(e)), on(
|
|
7799
|
+
}), on(document, "click", (e) => this._onDocClick(e)), on(globalThis, "scroll", () => this._updateOverlayPosition(), { passive: true }), on(globalThis, "resize", onWindowResize), on(editable, "scroll", () => this._updateOverlayPosition(), { passive: true }), on(editable, "dragstart", (e) => {
|
|
7886
7800
|
if (e.target instanceof Element && e.target.closest(".an-video-wrapper")) e.preventDefault();
|
|
7887
7801
|
}));
|
|
7888
7802
|
return this;
|
|
@@ -7899,7 +7813,7 @@
|
|
|
7899
7813
|
this._positionRaf = null;
|
|
7900
7814
|
}
|
|
7901
7815
|
this._deselect();
|
|
7902
|
-
|
|
7816
|
+
this._overlay?.remove();
|
|
7903
7817
|
this._overlay = null;
|
|
7904
7818
|
}
|
|
7905
7819
|
/** @returns {HTMLElement|null} */
|
|
@@ -7920,7 +7834,7 @@
|
|
|
7920
7834
|
*/
|
|
7921
7835
|
_findWrapper(el) {
|
|
7922
7836
|
if (!el || !(el instanceof Element)) return null;
|
|
7923
|
-
if (el.classList
|
|
7837
|
+
if (el.classList?.contains("an-video-wrapper")) return el;
|
|
7924
7838
|
const w = el.closest(".an-video-wrapper");
|
|
7925
7839
|
if (w) return w;
|
|
7926
7840
|
return null;
|
|
@@ -7953,7 +7867,7 @@
|
|
|
7953
7867
|
_onDocClick(e) {
|
|
7954
7868
|
if (!this._activeWrapper) return;
|
|
7955
7869
|
if (this._activeWrapper.contains(e.target)) return;
|
|
7956
|
-
if (this._overlay
|
|
7870
|
+
if (this._overlay?.contains(e.target)) return;
|
|
7957
7871
|
if (e.target.closest(".an-contextmenu")) return;
|
|
7958
7872
|
this._deselect();
|
|
7959
7873
|
}
|
|
@@ -8078,14 +7992,14 @@
|
|
|
8078
7992
|
}), on(editable, "mouseout", (e) => {
|
|
8079
7993
|
const to = e.relatedTarget;
|
|
8080
7994
|
if (!to || !editable.contains(to) && !this._el.contains(to)) this._scheduleHide();
|
|
8081
|
-
}), on(
|
|
7995
|
+
}), on(globalThis, "scroll", () => this._hide(), { passive: true }), on(globalThis, "resize", () => this._hide(), { passive: true }));
|
|
8082
7996
|
return this;
|
|
8083
7997
|
}
|
|
8084
7998
|
destroy() {
|
|
8085
7999
|
this._clearTimers();
|
|
8086
8000
|
this._disposers.forEach((d) => d());
|
|
8087
8001
|
this._disposers = [];
|
|
8088
|
-
if (this._el && this._el.parentNode) this._el.
|
|
8002
|
+
if (this._el && this._el.parentNode) this._el.remove();
|
|
8089
8003
|
this._el = null;
|
|
8090
8004
|
}
|
|
8091
8005
|
_buildTooltip() {
|
|
@@ -8170,8 +8084,8 @@
|
|
|
8170
8084
|
const margin = 6;
|
|
8171
8085
|
let top = rect.bottom + margin;
|
|
8172
8086
|
let left = rect.left;
|
|
8173
|
-
if (top + tipH >
|
|
8174
|
-
if (left + tipW >
|
|
8087
|
+
if (top + tipH > globalThis.innerHeight - margin) top = rect.top - tipH - margin;
|
|
8088
|
+
if (left + tipW > globalThis.innerWidth - margin) left = globalThis.innerWidth - tipW - margin;
|
|
8175
8089
|
if (left < margin) left = margin;
|
|
8176
8090
|
this._el.style.top = `${top}px`;
|
|
8177
8091
|
this._el.style.left = `${left}px`;
|
|
@@ -8186,12 +8100,12 @@
|
|
|
8186
8100
|
}
|
|
8187
8101
|
}
|
|
8188
8102
|
_openLink() {
|
|
8189
|
-
const url = this._activeAnchor
|
|
8190
|
-
if (url)
|
|
8103
|
+
const url = this._activeAnchor?.getAttribute("href");
|
|
8104
|
+
if (url) globalThis.open(url, "_blank", "noopener,noreferrer");
|
|
8191
8105
|
this._hide();
|
|
8192
8106
|
}
|
|
8193
8107
|
_copyLink() {
|
|
8194
|
-
const url = this._activeAnchor
|
|
8108
|
+
const url = this._activeAnchor?.getAttribute("href");
|
|
8195
8109
|
if (url) navigator.clipboard.writeText(url).catch(() => {
|
|
8196
8110
|
const ta = document.createElement("textarea");
|
|
8197
8111
|
ta.value = url;
|
|
@@ -8200,7 +8114,7 @@
|
|
|
8200
8114
|
document.body.appendChild(ta);
|
|
8201
8115
|
ta.select();
|
|
8202
8116
|
document.execCommand("copy");
|
|
8203
|
-
|
|
8117
|
+
ta.remove();
|
|
8204
8118
|
});
|
|
8205
8119
|
if (this._copyBtn) {
|
|
8206
8120
|
this._copyBtn.classList.add("an-link-tooltip-btn--copied");
|
|
@@ -8211,7 +8125,7 @@
|
|
|
8211
8125
|
const anchor = this._activeAnchor;
|
|
8212
8126
|
if (!anchor) return;
|
|
8213
8127
|
this._hide();
|
|
8214
|
-
const sel =
|
|
8128
|
+
const sel = globalThis.getSelection();
|
|
8215
8129
|
const range = document.createRange();
|
|
8216
8130
|
range.selectNodeContents(anchor);
|
|
8217
8131
|
sel.removeAllRanges();
|
|
@@ -8222,7 +8136,7 @@
|
|
|
8222
8136
|
const anchor = this._activeAnchor;
|
|
8223
8137
|
if (!anchor) return;
|
|
8224
8138
|
this._hide();
|
|
8225
|
-
const sel =
|
|
8139
|
+
const sel = globalThis.getSelection();
|
|
8226
8140
|
const range = document.createRange();
|
|
8227
8141
|
range.selectNode(anchor);
|
|
8228
8142
|
sel.removeAllRanges();
|
|
@@ -8271,14 +8185,14 @@
|
|
|
8271
8185
|
}, { passive: true }), on(document, "click", (e) => {
|
|
8272
8186
|
const et = e.target;
|
|
8273
8187
|
if (this._activeImg && !this._activeImg.contains(et) && !this._el.contains(et)) this._hide();
|
|
8274
|
-
}), on(
|
|
8188
|
+
}), on(globalThis, "scroll", () => this._hide(), { passive: true }), on(globalThis, "resize", () => this._hide(), { passive: true }));
|
|
8275
8189
|
return this;
|
|
8276
8190
|
}
|
|
8277
8191
|
destroy() {
|
|
8278
8192
|
this._clearTimers();
|
|
8279
8193
|
this._disposers.forEach((d) => d());
|
|
8280
8194
|
this._disposers = [];
|
|
8281
|
-
|
|
8195
|
+
this._el?.remove();
|
|
8282
8196
|
this._el = null;
|
|
8283
8197
|
}
|
|
8284
8198
|
_buildTooltip() {
|
|
@@ -8379,8 +8293,8 @@
|
|
|
8379
8293
|
const margin = 6;
|
|
8380
8294
|
let top = rect.bottom + margin;
|
|
8381
8295
|
let left = rect.left + (rect.width - tipW) / 2;
|
|
8382
|
-
if (top + tipH >
|
|
8383
|
-
if (left + tipW >
|
|
8296
|
+
if (top + tipH > globalThis.innerHeight - margin) top = rect.top - tipH - margin;
|
|
8297
|
+
if (left + tipW > globalThis.innerWidth - margin) left = globalThis.innerWidth - tipW - margin;
|
|
8384
8298
|
if (left < margin) left = margin;
|
|
8385
8299
|
this._el.style.top = `${top}px`;
|
|
8386
8300
|
this._el.style.left = `${left}px`;
|
|
@@ -8436,8 +8350,8 @@
|
|
|
8436
8350
|
const img = this._activeImg;
|
|
8437
8351
|
if (!img) return;
|
|
8438
8352
|
const current = img.style.transform || "";
|
|
8439
|
-
const match =
|
|
8440
|
-
const next = ((match ? parseFloat(match[1]) : 0) + delta + 360) % 360;
|
|
8353
|
+
const match = /rotate\((-?[\d.]+)deg\)/.exec(current);
|
|
8354
|
+
const next = ((match ? Number.parseFloat(match[1]) : 0) + delta + 360) % 360;
|
|
8441
8355
|
const cleaned = current.replace(/rotate\(-?[\d.]+deg\)/, "").trim();
|
|
8442
8356
|
img.style.transform = cleaned ? `${cleaned} rotate(${next}deg)` : next === 0 ? "" : `rotate(${next}deg)`;
|
|
8443
8357
|
this.context.invoke("editor.afterCommand");
|
|
@@ -8452,8 +8366,8 @@
|
|
|
8452
8366
|
this._hide();
|
|
8453
8367
|
this.context.invoke("imageResizer.deselect");
|
|
8454
8368
|
const figure = img.closest("figure.an-figure");
|
|
8455
|
-
if (figure
|
|
8456
|
-
else
|
|
8369
|
+
if (figure) figure.remove();
|
|
8370
|
+
else img.remove();
|
|
8457
8371
|
this.context.invoke("editor.afterCommand");
|
|
8458
8372
|
}
|
|
8459
8373
|
_crop() {
|
|
@@ -8472,7 +8386,7 @@
|
|
|
8472
8386
|
this._hide();
|
|
8473
8387
|
const range = document.createRange();
|
|
8474
8388
|
range.selectNodeContents(cap);
|
|
8475
|
-
const sel =
|
|
8389
|
+
const sel = globalThis.getSelection();
|
|
8476
8390
|
if (sel) {
|
|
8477
8391
|
sel.removeAllRanges();
|
|
8478
8392
|
sel.addRange(range);
|
|
@@ -8506,7 +8420,7 @@
|
|
|
8506
8420
|
figure.appendChild(figcaption);
|
|
8507
8421
|
const range = document.createRange();
|
|
8508
8422
|
range.selectNodeContents(figcaption);
|
|
8509
|
-
const sel =
|
|
8423
|
+
const sel = globalThis.getSelection();
|
|
8510
8424
|
if (sel) {
|
|
8511
8425
|
sel.removeAllRanges();
|
|
8512
8426
|
sel.addRange(range);
|
|
@@ -8547,8 +8461,7 @@
|
|
|
8547
8461
|
const editable = this.context.layoutInfo.editable;
|
|
8548
8462
|
this._disposers.push(on(editable, "mouseover", (e) => {
|
|
8549
8463
|
if (this.context.layoutInfo.container.classList.contains("an-disabled")) return;
|
|
8550
|
-
const
|
|
8551
|
-
const wrapper = target && target.closest ? target.closest(".an-video-wrapper") : null;
|
|
8464
|
+
const wrapper = e.target?.closest(".an-video-wrapper");
|
|
8552
8465
|
if (wrapper && editable.contains(wrapper)) this._scheduleShow(wrapper);
|
|
8553
8466
|
}, { passive: true }), on(editable, "mouseout", (e) => {
|
|
8554
8467
|
const to = e.relatedTarget;
|
|
@@ -8556,7 +8469,7 @@
|
|
|
8556
8469
|
}, { passive: true }), on(document, "click", (e) => {
|
|
8557
8470
|
const target = e.target;
|
|
8558
8471
|
if (this._activeWrapper && !this._activeWrapper.contains(target) && !this._el.contains(target)) this._hide();
|
|
8559
|
-
}), on(
|
|
8472
|
+
}), on(globalThis, "scroll", () => this._hide(), { passive: true }), on(globalThis, "resize", () => this._hide(), { passive: true }));
|
|
8560
8473
|
return this;
|
|
8561
8474
|
}
|
|
8562
8475
|
destroy() {
|
|
@@ -8564,7 +8477,7 @@
|
|
|
8564
8477
|
this._clearTimers();
|
|
8565
8478
|
this._disposers.forEach((d) => d());
|
|
8566
8479
|
this._disposers = [];
|
|
8567
|
-
|
|
8480
|
+
this._el?.remove();
|
|
8568
8481
|
this._el = null;
|
|
8569
8482
|
}
|
|
8570
8483
|
_buildTooltip() {
|
|
@@ -8661,8 +8574,8 @@
|
|
|
8661
8574
|
const margin = 6;
|
|
8662
8575
|
let top = rect.bottom + margin;
|
|
8663
8576
|
let left = rect.left + (rect.width - tipW) / 2;
|
|
8664
|
-
if (top + tipH >
|
|
8665
|
-
if (left + tipW >
|
|
8577
|
+
if (top + tipH > globalThis.innerHeight - margin) top = rect.top - tipH - margin;
|
|
8578
|
+
if (left + tipW > globalThis.innerWidth - margin) left = globalThis.innerWidth - tipW - margin;
|
|
8666
8579
|
if (left < margin) left = margin;
|
|
8667
8580
|
this._el.style.top = `${top}px`;
|
|
8668
8581
|
this._el.style.left = `${left}px`;
|
|
@@ -8716,7 +8629,7 @@
|
|
|
8716
8629
|
if (!wrapper) return;
|
|
8717
8630
|
this._hide();
|
|
8718
8631
|
this.context.invoke("videoResizer.deselect");
|
|
8719
|
-
|
|
8632
|
+
wrapper.remove();
|
|
8720
8633
|
this.context.invoke("editor.afterCommand");
|
|
8721
8634
|
}
|
|
8722
8635
|
_togglePreview() {
|
|
@@ -8958,12 +8871,12 @@
|
|
|
8958
8871
|
}, { passive: true }), on(editable, "mouseout", (e) => {
|
|
8959
8872
|
if (this._selectMode) return;
|
|
8960
8873
|
const to = e.relatedTarget;
|
|
8961
|
-
if (!to || !editable.contains(to) && !this._el.contains(to) && !
|
|
8874
|
+
if (!to || !editable.contains(to) && !this._el.contains(to) && !this._sizePopover?.contains(to)) this._scheduleHide();
|
|
8962
8875
|
}, { passive: true }), on(document, "click", (e) => {
|
|
8963
8876
|
const et = e.target;
|
|
8964
|
-
if (this._selectMode && this._activeTable
|
|
8965
|
-
if (this._activeTable && !this._activeTable.contains(et) && !this._el.contains(et) && !
|
|
8966
|
-
}), on(document, "selectionchange", () => this._syncShadeStrip()), on(
|
|
8877
|
+
if (this._selectMode && this._activeTable?.contains(et)) return;
|
|
8878
|
+
if (this._activeTable && !this._activeTable.contains(et) && !this._el.contains(et) && !this._sizePopover?.contains(et)) this._hide();
|
|
8879
|
+
}), on(document, "selectionchange", () => this._syncShadeStrip()), on(globalThis, "scroll", () => this._hide(), { passive: true }), on(globalThis, "resize", () => this._hide(), { passive: true }));
|
|
8967
8880
|
this._initResize();
|
|
8968
8881
|
return this;
|
|
8969
8882
|
}
|
|
@@ -9089,11 +9002,11 @@
|
|
|
9089
9002
|
this._clearTimers();
|
|
9090
9003
|
this._disposers.forEach((d) => d());
|
|
9091
9004
|
this._disposers = [];
|
|
9092
|
-
if (this._el && this._el.parentNode) this._el.
|
|
9005
|
+
if (this._el && this._el.parentNode) this._el.remove();
|
|
9093
9006
|
this._el = null;
|
|
9094
|
-
if (this._sizePopover && this._sizePopover.parentNode) this._sizePopover.
|
|
9007
|
+
if (this._sizePopover && this._sizePopover.parentNode) this._sizePopover.remove();
|
|
9095
9008
|
this._sizePopover = null;
|
|
9096
|
-
if (this._shadePopover && this._shadePopover.parentNode) this._shadePopover.
|
|
9009
|
+
if (this._shadePopover && this._shadePopover.parentNode) this._shadePopover.remove();
|
|
9097
9010
|
this._shadePopover = null;
|
|
9098
9011
|
}
|
|
9099
9012
|
_buildTooltip() {
|
|
@@ -9203,7 +9116,7 @@
|
|
|
9203
9116
|
_syncShadeStrip() {
|
|
9204
9117
|
if (!this._shadeColorStrip || !this._el || this._el.style.display === "none") return;
|
|
9205
9118
|
const cell = this._getCell();
|
|
9206
|
-
this._shadeColorStrip.style.background = cell
|
|
9119
|
+
this._shadeColorStrip.style.background = cell?.style.backgroundColor || "transparent";
|
|
9207
9120
|
}
|
|
9208
9121
|
_hide() {
|
|
9209
9122
|
this._el.style.display = "none";
|
|
@@ -9233,20 +9146,20 @@
|
|
|
9233
9146
|
let left = rect.left + (rect.width - tipW) / 2;
|
|
9234
9147
|
let top = rect.top - tipH - margin;
|
|
9235
9148
|
if (top < margin) top = rect.bottom + margin;
|
|
9236
|
-
if (left + tipW >
|
|
9149
|
+
if (left + tipW > globalThis.innerWidth - margin) left = globalThis.innerWidth - tipW - margin;
|
|
9237
9150
|
if (left < margin) left = margin;
|
|
9238
9151
|
this._el.style.left = `${left}px`;
|
|
9239
9152
|
this._el.style.top = `${top}px`;
|
|
9240
9153
|
}
|
|
9241
9154
|
_getCell() {
|
|
9242
|
-
const sel =
|
|
9155
|
+
const sel = globalThis.getSelection();
|
|
9243
9156
|
if (sel && sel.rangeCount) {
|
|
9244
9157
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
9245
9158
|
if (container.nodeType === 3) container = container.parentElement;
|
|
9246
|
-
const cellFromSel = container
|
|
9247
|
-
if (cellFromSel && this._activeTable
|
|
9159
|
+
const cellFromSel = container?.closest("td, th");
|
|
9160
|
+
if (cellFromSel && this._activeTable?.contains(cellFromSel)) return cellFromSel;
|
|
9248
9161
|
}
|
|
9249
|
-
return this._activeCell || this._activeTable
|
|
9162
|
+
return this._activeCell || this._activeTable?.querySelector("td, th");
|
|
9250
9163
|
}
|
|
9251
9164
|
_toggleSelectMode() {
|
|
9252
9165
|
this._selectMode = !this._selectMode;
|
|
@@ -9345,11 +9258,12 @@
|
|
|
9345
9258
|
const table = cells[0].closest("table");
|
|
9346
9259
|
if (!table) return;
|
|
9347
9260
|
const allRows = Array.from(table.querySelectorAll("tr"));
|
|
9348
|
-
const
|
|
9261
|
+
const selectedRows = [...new Set(cells.map((c) => c.closest("tr")).filter(Boolean))];
|
|
9262
|
+
const refRow = selectedRows.reduce((best, r) => {
|
|
9349
9263
|
const bi = allRows.indexOf(best);
|
|
9350
9264
|
const ri = allRows.indexOf(r);
|
|
9351
9265
|
return position === "above" ? ri < bi ? r : best : ri > bi ? r : best;
|
|
9352
|
-
});
|
|
9266
|
+
}, selectedRows[0]);
|
|
9353
9267
|
const colCount = Array.from(refRow.cells).reduce((sum, c) => sum + (c.colSpan || 1), 0);
|
|
9354
9268
|
const newRow = document.createElement("tr");
|
|
9355
9269
|
const refCells = Array.from(refRow.cells);
|
|
@@ -9392,7 +9306,7 @@
|
|
|
9392
9306
|
if (selectedRows.filter((r) => r.closest("tbody")).length >= totalBodyRows) return;
|
|
9393
9307
|
this._activeCell = null;
|
|
9394
9308
|
this._clearSelection();
|
|
9395
|
-
selectedRows.forEach((r) => r.
|
|
9309
|
+
selectedRows.forEach((r) => r.remove());
|
|
9396
9310
|
requestAnimationFrame(() => this._positionNear(this._activeTable));
|
|
9397
9311
|
this.context.invoke("editor.afterCommand");
|
|
9398
9312
|
}
|
|
@@ -9414,7 +9328,7 @@
|
|
|
9414
9328
|
});
|
|
9415
9329
|
this._activeCell = null;
|
|
9416
9330
|
this._clearSelection();
|
|
9417
|
-
cellsToDelete.forEach((c) => c.
|
|
9331
|
+
cellsToDelete.forEach((c) => c.remove());
|
|
9418
9332
|
requestAnimationFrame(() => this._positionNear(this._activeTable));
|
|
9419
9333
|
this.context.invoke("editor.afterCommand");
|
|
9420
9334
|
}
|
|
@@ -9425,7 +9339,7 @@
|
|
|
9425
9339
|
if (!table) return;
|
|
9426
9340
|
let selected = this._getSelectedCells().filter((c) => table.contains(c));
|
|
9427
9341
|
if (selected.length < 2) {
|
|
9428
|
-
const sel =
|
|
9342
|
+
const sel = globalThis.getSelection();
|
|
9429
9343
|
if (!sel || sel.rangeCount === 0) return;
|
|
9430
9344
|
const range = sel.getRangeAt(0);
|
|
9431
9345
|
selected = Array.from(table.querySelectorAll("td, th")).filter((c) => {
|
|
@@ -9467,7 +9381,7 @@
|
|
|
9467
9381
|
first.rowSpan = maxR - minR + 1;
|
|
9468
9382
|
first.style.verticalAlign = "middle";
|
|
9469
9383
|
first.innerHTML = rectCells.map((c) => c.innerHTML).join("");
|
|
9470
|
-
rectCells.slice(1).forEach((c) => c.
|
|
9384
|
+
rectCells.slice(1).forEach((c) => c.remove());
|
|
9471
9385
|
this._clearSelection();
|
|
9472
9386
|
this.context.invoke("editor.afterCommand");
|
|
9473
9387
|
}
|
|
@@ -9475,7 +9389,7 @@
|
|
|
9475
9389
|
const table = this._activeTable;
|
|
9476
9390
|
if (!table) return;
|
|
9477
9391
|
this._hide();
|
|
9478
|
-
if (table.parentNode) table.
|
|
9392
|
+
if (table.parentNode) table.remove();
|
|
9479
9393
|
this.context.invoke("editor.afterCommand");
|
|
9480
9394
|
}
|
|
9481
9395
|
_unmergeCells() {
|
|
@@ -9564,7 +9478,7 @@
|
|
|
9564
9478
|
this._sizeInputEl = inputEl;
|
|
9565
9479
|
this._sizeApply = null;
|
|
9566
9480
|
const d1 = on(applyBtn, "click", () => {
|
|
9567
|
-
const val = parseInt(this._sizeInputEl.value, 10);
|
|
9481
|
+
const val = Number.parseInt(this._sizeInputEl.value, 10);
|
|
9568
9482
|
if (val > 0 && typeof this._sizeApply === "function") this._sizeApply(val);
|
|
9569
9483
|
this._hideSizePopover();
|
|
9570
9484
|
});
|
|
@@ -9593,7 +9507,7 @@
|
|
|
9593
9507
|
const table = cell.closest("table");
|
|
9594
9508
|
if (!table) return;
|
|
9595
9509
|
const firstCell = table.querySelector("td, th");
|
|
9596
|
-
const currentPx = firstCell ? parseInt(firstCell.style.borderWidth, 10) || parseInt(
|
|
9510
|
+
const currentPx = firstCell ? Number.parseInt(firstCell.style.borderWidth, 10) || Number.parseInt(globalThis.getComputedStyle(firstCell).borderWidth, 10) || 1 : 1;
|
|
9597
9511
|
this._sizeTitleEl.textContent = this.context.locale.tooltips.table.tableBorderWidthPx;
|
|
9598
9512
|
this._sizeInputEl.min = "0";
|
|
9599
9513
|
this._sizeInputEl.max = "10";
|
|
@@ -9652,8 +9566,8 @@
|
|
|
9652
9566
|
const ph = this._sizePopover.offsetHeight || 110;
|
|
9653
9567
|
let left = tipRect.left;
|
|
9654
9568
|
let top = tipRect.bottom + 6;
|
|
9655
|
-
if (left + pw >
|
|
9656
|
-
if (top + ph >
|
|
9569
|
+
if (left + pw > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;
|
|
9570
|
+
if (top + ph > globalThis.innerHeight - 8) top = tipRect.top - ph - 6;
|
|
9657
9571
|
this._sizePopover.style.left = `${left}px`;
|
|
9658
9572
|
this._sizePopover.style.top = `${top}px`;
|
|
9659
9573
|
if (this._sizeInputEl) {
|
|
@@ -9707,11 +9621,10 @@
|
|
|
9707
9621
|
customRow.appendChild(colorInput);
|
|
9708
9622
|
customRow.appendChild(customLabel);
|
|
9709
9623
|
pop.appendChild(customRow);
|
|
9710
|
-
this._disposers.push(on(pop, "mousedown", (e) => e.preventDefault()));
|
|
9711
|
-
this._disposers.push(on(pop, "mouseenter", () => this._clearTimers()), on(pop, "mouseleave", () => this._scheduleHide()));
|
|
9624
|
+
this._disposers.push(on(pop, "mousedown", (e) => e.preventDefault()), on(pop, "mouseenter", () => this._clearTimers()), on(pop, "mouseleave", () => this._scheduleHide()));
|
|
9712
9625
|
this._disposers.push(on(document, "click", (e) => {
|
|
9713
9626
|
const et = e.target;
|
|
9714
|
-
if (this._shadePopover && this._shadePopover.style.display !== "none" && !this._shadePopover.contains(et) && !
|
|
9627
|
+
if (this._shadePopover && this._shadePopover.style.display !== "none" && !this._shadePopover.contains(et) && !this._el?.contains(et)) this._hideCellShadePopover();
|
|
9715
9628
|
}));
|
|
9716
9629
|
return pop;
|
|
9717
9630
|
}
|
|
@@ -9728,8 +9641,8 @@
|
|
|
9728
9641
|
const tipRect = this._el.getBoundingClientRect();
|
|
9729
9642
|
let left = tipRect.left;
|
|
9730
9643
|
let top = tipRect.bottom + 6;
|
|
9731
|
-
if (left + pw >
|
|
9732
|
-
if (top + ph >
|
|
9644
|
+
if (left + pw > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;
|
|
9645
|
+
if (top + ph > globalThis.innerHeight - 8) top = tipRect.top - ph - 6;
|
|
9733
9646
|
this._shadePopover.style.left = `${Math.max(8, left)}px`;
|
|
9734
9647
|
this._shadePopover.style.top = `${Math.max(8, top)}px`;
|
|
9735
9648
|
});
|
|
@@ -9792,7 +9705,7 @@
|
|
|
9792
9705
|
this._clearTimers();
|
|
9793
9706
|
this._disposers.forEach((d) => d());
|
|
9794
9707
|
this._disposers = [];
|
|
9795
|
-
|
|
9708
|
+
this._el?.remove();
|
|
9796
9709
|
this._el = null;
|
|
9797
9710
|
}
|
|
9798
9711
|
_buildTooltip() {
|
|
@@ -9918,21 +9831,21 @@
|
|
|
9918
9831
|
let top = rect.top - tipH - margin;
|
|
9919
9832
|
let left = rect.left + (rect.width - tipW) / 2;
|
|
9920
9833
|
if (top < margin) top = rect.bottom + margin;
|
|
9921
|
-
if (left + tipW >
|
|
9834
|
+
if (left + tipW > globalThis.innerWidth - margin) left = globalThis.innerWidth - tipW - margin;
|
|
9922
9835
|
if (left < margin) left = margin;
|
|
9923
9836
|
this._el.style.top = `${top}px`;
|
|
9924
9837
|
this._el.style.left = `${left}px`;
|
|
9925
9838
|
}
|
|
9926
9839
|
_syncWrapBtn() {
|
|
9927
9840
|
if (!this._activePre || !this._wrapBtn) return;
|
|
9928
|
-
const wrapped = (this._activePre.style.whiteSpace || "").includes("pre-wrap") ||
|
|
9841
|
+
const wrapped = (this._activePre.style.whiteSpace || "").includes("pre-wrap") || globalThis.getComputedStyle(this._activePre).whiteSpace === "pre-wrap";
|
|
9929
9842
|
this._wrapBtn.classList.toggle("active", wrapped);
|
|
9930
9843
|
this._wrapBtn.title = wrapped ? this.context.locale.tooltips.code.disableWordWrap : this.context.locale.tooltips.code.enableWordWrap;
|
|
9931
9844
|
}
|
|
9932
9845
|
_syncLangSelect() {
|
|
9933
9846
|
if (!this._activePre || !this._langSelect) return;
|
|
9934
9847
|
const codeEl = this._activePre.querySelector("code");
|
|
9935
|
-
const fromAttr = this._activePre.
|
|
9848
|
+
const fromAttr = this._activePre.dataset.language || "";
|
|
9936
9849
|
const fromClass = codeEl ? (_LANG_CLASS_RE.exec(codeEl.className) || [])[1] || "" : "";
|
|
9937
9850
|
this._langSelect.value = fromAttr || fromClass || "";
|
|
9938
9851
|
}
|
|
@@ -9951,7 +9864,7 @@
|
|
|
9951
9864
|
document.execCommand("copy");
|
|
9952
9865
|
this._flashCopied();
|
|
9953
9866
|
} catch (_) {}
|
|
9954
|
-
|
|
9867
|
+
ta.remove();
|
|
9955
9868
|
}
|
|
9956
9869
|
}
|
|
9957
9870
|
_flashCopied() {
|
|
@@ -9984,7 +9897,6 @@
|
|
|
9984
9897
|
applyLanguage(pre, lang) {
|
|
9985
9898
|
if (!pre || !lang) return;
|
|
9986
9899
|
const savedPre = this._activePre;
|
|
9987
|
-
this._langSelect && this._langSelect.value;
|
|
9988
9900
|
this._activePre = pre;
|
|
9989
9901
|
if (this._langSelect) this._langSelect.value = lang;
|
|
9990
9902
|
this._onLangChange();
|
|
@@ -9995,7 +9907,7 @@
|
|
|
9995
9907
|
const pre = this._activePre;
|
|
9996
9908
|
if (!pre) return;
|
|
9997
9909
|
const lang = this._langSelect.value;
|
|
9998
|
-
const _w =
|
|
9910
|
+
const _w = globalThis;
|
|
9999
9911
|
let codeEl = pre.querySelector("code");
|
|
10000
9912
|
if (!codeEl) {
|
|
10001
9913
|
codeEl = document.createElement("code");
|
|
@@ -10005,15 +9917,15 @@
|
|
|
10005
9917
|
}
|
|
10006
9918
|
codeEl.className = lang ? `language-${lang}` : "";
|
|
10007
9919
|
pre.className = lang ? `language-${lang}` : "";
|
|
10008
|
-
if (lang) pre.
|
|
10009
|
-
else pre.
|
|
9920
|
+
if (lang) pre.dataset.language = lang;
|
|
9921
|
+
else delete pre.dataset.language;
|
|
10010
9922
|
const applyPrism = () => {
|
|
10011
9923
|
codeEl.querySelectorAll("br").forEach((br) => br.replaceWith("\n"));
|
|
10012
9924
|
_w.Prism.highlightElement(codeEl);
|
|
10013
9925
|
this.context.invoke("editor.afterCommand");
|
|
10014
9926
|
};
|
|
10015
9927
|
if (lang) {
|
|
10016
|
-
if (
|
|
9928
|
+
if (_w.Prism !== void 0) {
|
|
10017
9929
|
if (_w.Prism.languages[lang]) {
|
|
10018
9930
|
applyPrism();
|
|
10019
9931
|
return;
|
|
@@ -10035,7 +9947,7 @@
|
|
|
10035
9947
|
* Called once at initialize time. Fire-and-forget; errors are silent.
|
|
10036
9948
|
*/
|
|
10037
9949
|
_ensurePrism() {
|
|
10038
|
-
const _w =
|
|
9950
|
+
const _w = globalThis;
|
|
10039
9951
|
if (!this.context.options.codeHighlight || _w.Prism) return;
|
|
10040
9952
|
const cdn = this.context.options.codeHighlightCDN;
|
|
10041
9953
|
const themeHref = `${cdn}/themes/prism-tomorrow.min.css`;
|
|
@@ -10068,11 +9980,11 @@
|
|
|
10068
9980
|
* @param {Function} cb – called once the grammar is ready
|
|
10069
9981
|
*/
|
|
10070
9982
|
_loadPrismComponent(lang, cb) {
|
|
10071
|
-
const _w =
|
|
9983
|
+
const _w = globalThis;
|
|
10072
9984
|
const src = `${this.context.options.codeHighlightCDN}/components/prism-${lang}.min.js`;
|
|
10073
9985
|
if (document.querySelector(`script[src="${src}"]`)) {
|
|
10074
9986
|
const poll = setInterval(() => {
|
|
10075
|
-
if (_w.Prism
|
|
9987
|
+
if (_w.Prism?.languages[lang]) {
|
|
10076
9988
|
clearInterval(poll);
|
|
10077
9989
|
cb();
|
|
10078
9990
|
}
|
|
@@ -10103,7 +10015,7 @@
|
|
|
10103
10015
|
const pre = this._activePre;
|
|
10104
10016
|
if (!pre) return;
|
|
10105
10017
|
this._hide();
|
|
10106
|
-
|
|
10018
|
+
pre.remove();
|
|
10107
10019
|
this.context.invoke("editor.afterCommand");
|
|
10108
10020
|
}
|
|
10109
10021
|
};
|
|
@@ -12458,7 +12370,7 @@
|
|
|
12458
12370
|
destroy() {
|
|
12459
12371
|
this._disposers.forEach((d) => d());
|
|
12460
12372
|
this._disposers = [];
|
|
12461
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.
|
|
12373
|
+
if (this._dialog && this._dialog.parentNode) this._dialog.remove();
|
|
12462
12374
|
this._dialog = null;
|
|
12463
12375
|
}
|
|
12464
12376
|
show() {
|
|
@@ -12519,7 +12431,7 @@
|
|
|
12519
12431
|
class: "an-icon-cat",
|
|
12520
12432
|
"data-cat": id
|
|
12521
12433
|
});
|
|
12522
|
-
tab.textContent = L.categories
|
|
12434
|
+
tab.textContent = L.categories?.[id] || label;
|
|
12523
12435
|
catBar.appendChild(tab);
|
|
12524
12436
|
});
|
|
12525
12437
|
this._catBar = catBar;
|
|
@@ -12600,7 +12512,7 @@
|
|
|
12600
12512
|
const savedRange = this._savedRange;
|
|
12601
12513
|
const editable = this.context.layoutInfo.editable;
|
|
12602
12514
|
if (savedRange) savedRange.select();
|
|
12603
|
-
const sel =
|
|
12515
|
+
const sel = globalThis.getSelection();
|
|
12604
12516
|
let range = sel && sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
|
|
12605
12517
|
if (!range) {
|
|
12606
12518
|
range = document.createRange();
|
|
@@ -12610,7 +12522,7 @@
|
|
|
12610
12522
|
const _sc = range.startContainer;
|
|
12611
12523
|
const _tdAnchor = (_sc.nodeType === 1 ? _sc : _sc.parentElement)?.closest("td, th");
|
|
12612
12524
|
range.deleteContents();
|
|
12613
|
-
if (_tdAnchor
|
|
12525
|
+
if (_tdAnchor?.isConnected && !_tdAnchor.contains(range.startContainer)) {
|
|
12614
12526
|
range.setStart(_tdAnchor, 0);
|
|
12615
12527
|
range.collapse(true);
|
|
12616
12528
|
}
|
|
@@ -12630,7 +12542,7 @@
|
|
|
12630
12542
|
if (this._dialog) {
|
|
12631
12543
|
this._dialog.style.display = "flex";
|
|
12632
12544
|
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
12633
|
-
setTimeout(() => this._searchInput
|
|
12545
|
+
setTimeout(() => this._searchInput?.focus(), 50);
|
|
12634
12546
|
}
|
|
12635
12547
|
}
|
|
12636
12548
|
_close() {
|
|
@@ -12937,7 +12849,7 @@
|
|
|
12937
12849
|
destroy() {
|
|
12938
12850
|
this._disposers.forEach((d) => d());
|
|
12939
12851
|
this._disposers = [];
|
|
12940
|
-
|
|
12852
|
+
this._dialog?.remove();
|
|
12941
12853
|
this._dialog = null;
|
|
12942
12854
|
}
|
|
12943
12855
|
show() {
|
|
@@ -13002,7 +12914,7 @@
|
|
|
13002
12914
|
class: "an-icon-cat",
|
|
13003
12915
|
"data-cat": id
|
|
13004
12916
|
});
|
|
13005
|
-
tab.textContent = L.categories
|
|
12917
|
+
tab.textContent = L.categories?.[id] || label;
|
|
13006
12918
|
catBar.appendChild(tab);
|
|
13007
12919
|
});
|
|
13008
12920
|
this._catBar = catBar;
|
|
@@ -13170,17 +13082,17 @@
|
|
|
13170
13082
|
this._preview.innerHTML = "<span class=\"an-icon-preview-hint\">Select an icon</span>";
|
|
13171
13083
|
return;
|
|
13172
13084
|
}
|
|
13173
|
-
const cls = this._styleSelect
|
|
13174
|
-
const size = this._sizeSelect
|
|
13175
|
-
const color =
|
|
13085
|
+
const cls = this._styleSelect?.value || "fa-solid";
|
|
13086
|
+
const size = this._sizeSelect?.value || "1em";
|
|
13087
|
+
const color = this._useColorCb?.checked ?? false ? this._colorInput?.value ?? "" : "";
|
|
13176
13088
|
const styleAttr = [size ? `font-size:${size}` : "", color ? `color:${color}` : ""].filter(Boolean).join(";");
|
|
13177
13089
|
this._preview.innerHTML = `<i class="${cls} fa-${name}" aria-hidden="true"${styleAttr ? ` style="${styleAttr}"` : ""}></i><div class="an-icon-preview-name">${cls} fa-${name}</div>`;
|
|
13178
13090
|
}
|
|
13179
13091
|
_onInsert() {
|
|
13180
13092
|
if (!this._selectedIcon) return;
|
|
13181
|
-
const cls = this._styleSelect
|
|
13182
|
-
const size = this._sizeSelect
|
|
13183
|
-
const color =
|
|
13093
|
+
const cls = this._styleSelect?.value || "fa-solid";
|
|
13094
|
+
const size = this._sizeSelect?.value || "";
|
|
13095
|
+
const color = this._useColorCb?.checked ?? false ? this._colorInput?.value ?? "" : "";
|
|
13184
13096
|
const styleParts = [size ? `font-size:${size}` : "", color ? `color:${color}` : ""].filter(Boolean);
|
|
13185
13097
|
const iconEl = document.createElement("i");
|
|
13186
13098
|
iconEl.className = `${cls} fa-${this._selectedIcon}`;
|
|
@@ -13190,8 +13102,8 @@
|
|
|
13190
13102
|
const savedRange = this._savedRange;
|
|
13191
13103
|
const editable = this.context.layoutInfo.editable;
|
|
13192
13104
|
if (savedRange) savedRange.select();
|
|
13193
|
-
const sel =
|
|
13194
|
-
let range = sel
|
|
13105
|
+
const sel = globalThis.getSelection();
|
|
13106
|
+
let range = (sel?.rangeCount ?? 0) > 0 ? sel.getRangeAt(0) : null;
|
|
13195
13107
|
if (!range) {
|
|
13196
13108
|
range = document.createRange();
|
|
13197
13109
|
range.selectNodeContents(editable);
|
|
@@ -13230,7 +13142,7 @@
|
|
|
13230
13142
|
if (this._dialog) {
|
|
13231
13143
|
this._dialog.style.display = "flex";
|
|
13232
13144
|
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
13233
|
-
setTimeout(() => this._searchInput
|
|
13145
|
+
setTimeout(() => this._searchInput?.focus(), 50);
|
|
13234
13146
|
}
|
|
13235
13147
|
}
|
|
13236
13148
|
_close() {
|
|
@@ -13331,7 +13243,7 @@
|
|
|
13331
13243
|
icon: ICONS.paste,
|
|
13332
13244
|
action: (ctx) => {
|
|
13333
13245
|
if (!navigator.clipboard) return;
|
|
13334
|
-
const editable = ctx.layoutInfo
|
|
13246
|
+
const editable = ctx.layoutInfo?.editable;
|
|
13335
13247
|
if (!editable) return;
|
|
13336
13248
|
const doInsert = (html, text) => {
|
|
13337
13249
|
editable.focus();
|
|
@@ -13456,13 +13368,13 @@
|
|
|
13456
13368
|
this.el.style.display = "none";
|
|
13457
13369
|
document.body.appendChild(this.el);
|
|
13458
13370
|
this._renderItems(this._items);
|
|
13459
|
-
const editable = this.context.layoutInfo
|
|
13371
|
+
const editable = this.context.layoutInfo?.editable;
|
|
13460
13372
|
if (editable) this._disposers.push(on(editable, "contextmenu", (e) => this._onContextMenu(e)));
|
|
13461
13373
|
this._disposers.push(on(document, "click", (e) => this._maybeHide(e)));
|
|
13462
13374
|
this._disposers.push(on(document, "keydown", (e) => {
|
|
13463
13375
|
if (e.key === "Escape") this.hide();
|
|
13464
13376
|
}));
|
|
13465
|
-
this._disposers.push(on(
|
|
13377
|
+
this._disposers.push(on(globalThis, "scroll", () => this.hide(), { passive: true }));
|
|
13466
13378
|
return this;
|
|
13467
13379
|
}
|
|
13468
13380
|
destroy() {
|
|
@@ -13478,7 +13390,7 @@
|
|
|
13478
13390
|
} catch (_e) {}
|
|
13479
13391
|
});
|
|
13480
13392
|
this._disposers = [];
|
|
13481
|
-
if (this.el
|
|
13393
|
+
if (this.el) this.el.remove();
|
|
13482
13394
|
this.el = null;
|
|
13483
13395
|
}
|
|
13484
13396
|
_renderItems(items) {
|
|
@@ -13506,8 +13418,8 @@
|
|
|
13506
13418
|
backBtn.appendChild(createElement("span", { class: "an-context-label" }, [backLabel]));
|
|
13507
13419
|
const off = on(backBtn, "click", (e) => {
|
|
13508
13420
|
e.stopPropagation();
|
|
13509
|
-
const curLeft = parseFloat(this.el.style.left);
|
|
13510
|
-
const curTop = parseFloat(this.el.style.top);
|
|
13421
|
+
const curLeft = Number.parseFloat(this.el.style.left);
|
|
13422
|
+
const curTop = Number.parseFloat(this.el.style.top);
|
|
13511
13423
|
this._renderItems(it.navigate());
|
|
13512
13424
|
this._reposition(curLeft, curTop);
|
|
13513
13425
|
});
|
|
@@ -13550,8 +13462,8 @@
|
|
|
13550
13462
|
btn.appendChild(chevron);
|
|
13551
13463
|
const off = on(btn, "click", (e) => {
|
|
13552
13464
|
e.stopPropagation();
|
|
13553
|
-
const curLeft = parseFloat(this.el.style.left);
|
|
13554
|
-
const curTop = parseFloat(this.el.style.top);
|
|
13465
|
+
const curLeft = Number.parseFloat(this.el.style.left);
|
|
13466
|
+
const curTop = Number.parseFloat(this.el.style.top);
|
|
13555
13467
|
this._renderItems(it.navigate());
|
|
13556
13468
|
this._reposition(curLeft, curTop);
|
|
13557
13469
|
});
|
|
@@ -13676,10 +13588,10 @@
|
|
|
13676
13588
|
if (!cell) return;
|
|
13677
13589
|
const rows = +cell.dataset.row;
|
|
13678
13590
|
const cols = +cell.dataset.col;
|
|
13679
|
-
const editable = this.context.layoutInfo
|
|
13591
|
+
const editable = this.context.layoutInfo?.editable;
|
|
13680
13592
|
if (editable && this._savedRange) {
|
|
13681
13593
|
editable.focus();
|
|
13682
|
-
const sel =
|
|
13594
|
+
const sel = globalThis.getSelection();
|
|
13683
13595
|
sel.removeAllRanges();
|
|
13684
13596
|
sel.addRange(this._savedRange.cloneRange());
|
|
13685
13597
|
}
|
|
@@ -13721,12 +13633,12 @@
|
|
|
13721
13633
|
});
|
|
13722
13634
|
}
|
|
13723
13635
|
_onContextMenu(event) {
|
|
13724
|
-
const editable = this.context.layoutInfo
|
|
13636
|
+
const editable = this.context.layoutInfo?.editable;
|
|
13725
13637
|
if (!editable) return;
|
|
13726
13638
|
if (!editable.contains(event.target)) return;
|
|
13727
13639
|
if (this.context.layoutInfo.container.classList.contains("an-disabled")) return;
|
|
13728
13640
|
event.preventDefault();
|
|
13729
|
-
const winSel =
|
|
13641
|
+
const winSel = globalThis.getSelection();
|
|
13730
13642
|
this._savedRange = winSel && winSel.rangeCount > 0 ? winSel.getRangeAt(0).cloneRange() : null;
|
|
13731
13643
|
this._renderItems(this._items);
|
|
13732
13644
|
const openX = event.clientX;
|
|
@@ -13758,9 +13670,9 @@
|
|
|
13758
13670
|
const h = this.el.offsetHeight;
|
|
13759
13671
|
let left = rx;
|
|
13760
13672
|
let top = ry;
|
|
13761
|
-
if (left + w >
|
|
13673
|
+
if (left + w > globalThis.innerWidth - 8) left = globalThis.innerWidth - w - 8;
|
|
13762
13674
|
if (left < 8) left = 8;
|
|
13763
|
-
if (top + h >
|
|
13675
|
+
if (top + h > globalThis.innerHeight - 8) top = globalThis.innerHeight - h - 8;
|
|
13764
13676
|
if (top < 8) top = 8;
|
|
13765
13677
|
this.el.style.left = `${left}px`;
|
|
13766
13678
|
this.el.style.top = `${top}px`;
|
|
@@ -13781,17 +13693,17 @@
|
|
|
13781
13693
|
let node = range.startContainer;
|
|
13782
13694
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
13783
13695
|
if (!node) return type === "foreColor" ? "#000000" : "transparent";
|
|
13784
|
-
const cs =
|
|
13696
|
+
const cs = globalThis.getComputedStyle(node);
|
|
13785
13697
|
if (type === "foreColor") return cs.color || "#000000";
|
|
13786
13698
|
const bg = cs.backgroundColor;
|
|
13787
13699
|
return !bg || bg === "rgba(0, 0, 0, 0)" || bg === "transparent" ? "transparent" : bg;
|
|
13788
13700
|
}
|
|
13789
13701
|
/** Restore selection, apply a color command, then hide the menu. */
|
|
13790
13702
|
_applyColor(type, color) {
|
|
13791
|
-
const editable = this.context.layoutInfo
|
|
13703
|
+
const editable = this.context.layoutInfo?.editable;
|
|
13792
13704
|
if (!editable || !this._savedRange) return;
|
|
13793
13705
|
editable.focus();
|
|
13794
|
-
const sel =
|
|
13706
|
+
const sel = globalThis.getSelection();
|
|
13795
13707
|
sel.removeAllRanges();
|
|
13796
13708
|
sel.addRange(this._savedRange.cloneRange());
|
|
13797
13709
|
document.execCommand(type, false, color);
|
|
@@ -13806,15 +13718,15 @@
|
|
|
13806
13718
|
copyFormat() {
|
|
13807
13719
|
const range = this._savedRange;
|
|
13808
13720
|
if (!range) return;
|
|
13809
|
-
const editable = this.context.layoutInfo
|
|
13721
|
+
const editable = this.context.layoutInfo?.editable;
|
|
13810
13722
|
let node = range.startContainer;
|
|
13811
13723
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
13812
13724
|
if (!node || !editable || !editable.contains(node)) return;
|
|
13813
|
-
const cs =
|
|
13725
|
+
const cs = globalThis.getComputedStyle(node);
|
|
13814
13726
|
const explicitFontFamily = this._findExplicitStyle(node, editable, "fontFamily");
|
|
13815
13727
|
const explicitFontSize = this._findExplicitStyle(node, editable, "fontSize");
|
|
13816
13728
|
this._copiedFormat = {
|
|
13817
|
-
bold: parseInt(cs.fontWeight, 10) >= 700,
|
|
13729
|
+
bold: Number.parseInt(cs.fontWeight, 10) >= 700,
|
|
13818
13730
|
italic: cs.fontStyle === "italic" || cs.fontStyle === "oblique",
|
|
13819
13731
|
underline: (cs.textDecorationLine || "").includes("underline"),
|
|
13820
13732
|
strikethrough: (cs.textDecorationLine || "").includes("line-through"),
|
|
@@ -13845,10 +13757,10 @@
|
|
|
13845
13757
|
pasteFormat() {
|
|
13846
13758
|
if (!this._copiedFormat || !this._savedRange) return;
|
|
13847
13759
|
const fmt = this._copiedFormat;
|
|
13848
|
-
const editable = this.context.layoutInfo
|
|
13760
|
+
const editable = this.context.layoutInfo?.editable;
|
|
13849
13761
|
if (!editable) return;
|
|
13850
13762
|
editable.focus();
|
|
13851
|
-
const sel =
|
|
13763
|
+
const sel = globalThis.getSelection();
|
|
13852
13764
|
sel.removeAllRanges();
|
|
13853
13765
|
sel.addRange(this._savedRange.cloneRange());
|
|
13854
13766
|
document.execCommand("removeFormat");
|
|
@@ -13865,14 +13777,14 @@
|
|
|
13865
13777
|
const preExisting = new Set(editable.querySelectorAll("font[size=\"7\"]"));
|
|
13866
13778
|
document.execCommand("fontSize", false, "7");
|
|
13867
13779
|
editable.querySelectorAll("font[size=\"7\"]").forEach((el) => {
|
|
13868
|
-
if (!preExisting.has(el)) el.
|
|
13780
|
+
if (!preExisting.has(el)) /** @type {HTMLElement} */ el.dataset.anTmp = marker;
|
|
13869
13781
|
});
|
|
13870
13782
|
editable.querySelectorAll(`[data-an-tmp="${marker}"]`).forEach((el) => {
|
|
13871
13783
|
const span = document.createElement("span");
|
|
13872
13784
|
span.style.fontSize = fmt.fontSize;
|
|
13873
13785
|
el.parentNode.insertBefore(span, el);
|
|
13874
13786
|
while (el.firstChild) span.appendChild(el.firstChild);
|
|
13875
|
-
el.
|
|
13787
|
+
el.remove();
|
|
13876
13788
|
});
|
|
13877
13789
|
}
|
|
13878
13790
|
this.context.invoke("editor.afterCommand");
|
|
@@ -13880,10 +13792,10 @@
|
|
|
13880
13792
|
/** Strip all inline formatting from the saved selection. */
|
|
13881
13793
|
removeFormat() {
|
|
13882
13794
|
if (!this._savedRange) return;
|
|
13883
|
-
const editable = this.context.layoutInfo
|
|
13795
|
+
const editable = this.context.layoutInfo?.editable;
|
|
13884
13796
|
if (!editable) return;
|
|
13885
13797
|
editable.focus();
|
|
13886
|
-
const sel =
|
|
13798
|
+
const sel = globalThis.getSelection();
|
|
13887
13799
|
sel.removeAllRanges();
|
|
13888
13800
|
sel.addRange(this._savedRange.cloneRange());
|
|
13889
13801
|
document.execCommand("removeFormat");
|
|
@@ -13997,14 +13909,14 @@
|
|
|
13997
13909
|
destroy() {
|
|
13998
13910
|
this._disposers.forEach((d) => d());
|
|
13999
13911
|
this._disposers = [];
|
|
14000
|
-
|
|
13912
|
+
this._dialog?.remove();
|
|
14001
13913
|
this._dialog = null;
|
|
14002
13914
|
}
|
|
14003
13915
|
show() {
|
|
14004
13916
|
if (this._dialog) {
|
|
14005
13917
|
this._dialog.style.display = "flex";
|
|
14006
13918
|
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
14007
|
-
setTimeout(() => this._closeBtn
|
|
13919
|
+
setTimeout(() => this._closeBtn?.focus(), 50);
|
|
14008
13920
|
}
|
|
14009
13921
|
}
|
|
14010
13922
|
_close() {
|
|
@@ -14110,7 +14022,7 @@
|
|
|
14110
14022
|
this._clearHighlights();
|
|
14111
14023
|
this._disposers.forEach((d) => d());
|
|
14112
14024
|
this._disposers = [];
|
|
14113
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.
|
|
14025
|
+
if (this._dialog && this._dialog.parentNode) this._dialog.remove();
|
|
14114
14026
|
this._dialog = null;
|
|
14115
14027
|
}
|
|
14116
14028
|
/**
|
|
@@ -14353,15 +14265,19 @@
|
|
|
14353
14265
|
const re = this._queryRegex;
|
|
14354
14266
|
const MAX_RESULTS = 500;
|
|
14355
14267
|
const walker = document.createTreeWalker(root, 4);
|
|
14356
|
-
let node;
|
|
14357
|
-
while (
|
|
14268
|
+
let node = walker.nextNode();
|
|
14269
|
+
while (node && results.length < MAX_RESULTS) {
|
|
14358
14270
|
re.lastIndex = 0;
|
|
14359
14271
|
let m;
|
|
14360
|
-
while ((m = re.exec(
|
|
14272
|
+
while ((m = re.exec(
|
|
14273
|
+
/** @type {Text} */
|
|
14274
|
+
node.textContent
|
|
14275
|
+
)) !== null && results.length < MAX_RESULTS) results.push({
|
|
14361
14276
|
node,
|
|
14362
14277
|
start: m.index,
|
|
14363
14278
|
end: m.index + m[0].length
|
|
14364
14279
|
});
|
|
14280
|
+
node = walker.nextNode();
|
|
14365
14281
|
}
|
|
14366
14282
|
return results;
|
|
14367
14283
|
}
|
|
@@ -14396,7 +14312,7 @@
|
|
|
14396
14312
|
const parent = match.mark.parentNode;
|
|
14397
14313
|
const textNode = document.createTextNode(replacement);
|
|
14398
14314
|
parent.insertBefore(textNode, match.mark);
|
|
14399
|
-
|
|
14315
|
+
match.mark.remove();
|
|
14400
14316
|
parent.normalize();
|
|
14401
14317
|
this.context.invoke("editor.afterCommand");
|
|
14402
14318
|
const savedIndex = this._currentIndex;
|
|
@@ -14414,7 +14330,7 @@
|
|
|
14414
14330
|
if (!mark || !mark.parentNode) return;
|
|
14415
14331
|
const textNode = document.createTextNode(replacement);
|
|
14416
14332
|
mark.parentNode.insertBefore(textNode, mark);
|
|
14417
|
-
mark.
|
|
14333
|
+
mark.remove();
|
|
14418
14334
|
});
|
|
14419
14335
|
if (this.context.layoutInfo.editable) this.context.layoutInfo.editable.normalize();
|
|
14420
14336
|
this._matches = [];
|
|
@@ -14433,7 +14349,7 @@
|
|
|
14433
14349
|
const parent = mark.parentNode;
|
|
14434
14350
|
if (!parent) return;
|
|
14435
14351
|
while (mark.firstChild) parent.insertBefore(mark.firstChild, mark);
|
|
14436
|
-
|
|
14352
|
+
mark.remove();
|
|
14437
14353
|
});
|
|
14438
14354
|
editable.normalize();
|
|
14439
14355
|
this._matches = [];
|
|
@@ -14484,7 +14400,7 @@
|
|
|
14484
14400
|
resolve(null);
|
|
14485
14401
|
}
|
|
14486
14402
|
};
|
|
14487
|
-
if (img.src.startsWith("data:") || img.src.startsWith("blob:") || img.src.startsWith(
|
|
14403
|
+
if (img.src.startsWith("data:") || img.src.startsWith("blob:") || img.src.startsWith(globalThis.location.origin)) {
|
|
14488
14404
|
tryDraw(img);
|
|
14489
14405
|
return;
|
|
14490
14406
|
}
|
|
@@ -14742,8 +14658,8 @@
|
|
|
14742
14658
|
this._cropBox.style.top = `${y}px`;
|
|
14743
14659
|
this._cropBox.style.width = `${w}px`;
|
|
14744
14660
|
this._cropBox.style.height = `${h}px`;
|
|
14745
|
-
const vw =
|
|
14746
|
-
const vh =
|
|
14661
|
+
const vw = globalThis.innerWidth;
|
|
14662
|
+
const vh = globalThis.innerHeight;
|
|
14747
14663
|
this._scrim.style.clipPath = [
|
|
14748
14664
|
`polygon(`,
|
|
14749
14665
|
`0 0, ${vw}px 0, ${vw}px ${vh}px, 0 ${vh}px, 0 0,`,
|
|
@@ -14767,7 +14683,7 @@
|
|
|
14767
14683
|
}
|
|
14768
14684
|
const margin = 8;
|
|
14769
14685
|
let tbTop = y + h + margin;
|
|
14770
|
-
if (tbTop + 40 >
|
|
14686
|
+
if (tbTop + 40 > globalThis.innerHeight - margin) tbTop = y - 40 - margin;
|
|
14771
14687
|
this._toolbar.style.left = `${x}px`;
|
|
14772
14688
|
this._toolbar.style.top = `${tbTop}px`;
|
|
14773
14689
|
}
|
|
@@ -14894,7 +14810,7 @@
|
|
|
14894
14810
|
this._close(false);
|
|
14895
14811
|
return;
|
|
14896
14812
|
}
|
|
14897
|
-
const fmt =
|
|
14813
|
+
const fmt = /^data:image\/(jpe?g)/i.exec(img.src) ? "image/jpeg" : "image/png";
|
|
14898
14814
|
const quality = fmt === "image/jpeg" ? .92 : void 0;
|
|
14899
14815
|
const newSrc = canvas.toDataURL(fmt, quality);
|
|
14900
14816
|
this._close(false);
|
|
@@ -14934,7 +14850,7 @@
|
|
|
14934
14850
|
banner.textContent = msg;
|
|
14935
14851
|
document.body.appendChild(banner);
|
|
14936
14852
|
setTimeout(() => {
|
|
14937
|
-
|
|
14853
|
+
banner.remove();
|
|
14938
14854
|
}, 4e3);
|
|
14939
14855
|
}
|
|
14940
14856
|
/**
|
|
@@ -14949,7 +14865,7 @@
|
|
|
14949
14865
|
this._cropBox,
|
|
14950
14866
|
this._toolbar
|
|
14951
14867
|
].forEach((el) => {
|
|
14952
|
-
|
|
14868
|
+
el?.remove();
|
|
14953
14869
|
});
|
|
14954
14870
|
this._scrim = null;
|
|
14955
14871
|
this._cropBox = null;
|
|
@@ -14970,7 +14886,7 @@
|
|
|
14970
14886
|
*
|
|
14971
14887
|
* Activated when both `autoSave` and `autoSaveRestore` options are true.
|
|
14972
14888
|
* On initialize it checks localStorage for a draft that is within the
|
|
14973
|
-
* `autoSaveRestoreTimeout` day
|
|
14889
|
+
* `autoSaveRestoreTimeout` day globalThis. If one is found a dismissible banner
|
|
14974
14890
|
* is prepended to the editor container.
|
|
14975
14891
|
*/
|
|
14976
14892
|
var AutoSaveRestore = class {
|
|
@@ -15056,7 +14972,7 @@
|
|
|
15056
14972
|
this._removeBanner();
|
|
15057
14973
|
}
|
|
15058
14974
|
_removeBanner() {
|
|
15059
|
-
|
|
14975
|
+
this._banner?.remove();
|
|
15060
14976
|
this._banner = null;
|
|
15061
14977
|
}
|
|
15062
14978
|
};
|
|
@@ -15119,8 +15035,8 @@
|
|
|
15119
15035
|
* @returns {{ text: string, range: Range, lineNode: Node } | null}
|
|
15120
15036
|
*/
|
|
15121
15037
|
_getLineContext() {
|
|
15122
|
-
const sel =
|
|
15123
|
-
if (!sel
|
|
15038
|
+
const sel = globalThis.getSelection();
|
|
15039
|
+
if (!sel?.rangeCount) return null;
|
|
15124
15040
|
const range = sel.getRangeAt(0);
|
|
15125
15041
|
if (!range.collapsed) return null;
|
|
15126
15042
|
const editable = this.context.layoutInfo.editable;
|
|
@@ -15139,7 +15055,7 @@
|
|
|
15139
15055
|
}
|
|
15140
15056
|
_isBlock(node) {
|
|
15141
15057
|
if (node.nodeType !== Node.ELEMENT_NODE) return false;
|
|
15142
|
-
const display =
|
|
15058
|
+
const display = globalThis.getComputedStyle(node).display;
|
|
15143
15059
|
return display === "block" || display === "list-item" || display === "table-cell";
|
|
15144
15060
|
}
|
|
15145
15061
|
/** Applies block rule on Space key. Returns true if a rule fired. */
|
|
@@ -15170,7 +15086,7 @@
|
|
|
15170
15086
|
}
|
|
15171
15087
|
];
|
|
15172
15088
|
for (const { re, handler } of blockPatterns) {
|
|
15173
|
-
const m =
|
|
15089
|
+
const m = re.exec(text);
|
|
15174
15090
|
if (m) {
|
|
15175
15091
|
handler(m);
|
|
15176
15092
|
return true;
|
|
@@ -15194,8 +15110,8 @@
|
|
|
15194
15110
|
return false;
|
|
15195
15111
|
}
|
|
15196
15112
|
_selectLineAndDelete() {
|
|
15197
|
-
const sel =
|
|
15198
|
-
if (!sel
|
|
15113
|
+
const sel = globalThis.getSelection();
|
|
15114
|
+
if (!sel?.rangeCount) return;
|
|
15199
15115
|
const range = sel.getRangeAt(0);
|
|
15200
15116
|
const startRange = document.createRange();
|
|
15201
15117
|
startRange.setStart(range.startContainer.parentNode || range.startContainer, 0);
|
|
@@ -15233,8 +15149,8 @@
|
|
|
15233
15149
|
this.context.triggerEvent("change", this.context.getHTML());
|
|
15234
15150
|
}
|
|
15235
15151
|
_onInput() {
|
|
15236
|
-
const sel =
|
|
15237
|
-
if (!sel
|
|
15152
|
+
const sel = globalThis.getSelection();
|
|
15153
|
+
if (!sel?.rangeCount) return;
|
|
15238
15154
|
const range = sel.getRangeAt(0);
|
|
15239
15155
|
if (!range.collapsed) return;
|
|
15240
15156
|
if (!this.context.layoutInfo.editable.contains(range.startContainer)) return;
|
|
@@ -15262,7 +15178,7 @@
|
|
|
15262
15178
|
];
|
|
15263
15179
|
const upToCursor = text.slice(0, offset);
|
|
15264
15180
|
for (const { re, tag } of inlineRules) {
|
|
15265
|
-
const m =
|
|
15181
|
+
const m = re.exec(upToCursor);
|
|
15266
15182
|
if (!m) continue;
|
|
15267
15183
|
const matchStart = upToCursor.length - m[0].length;
|
|
15268
15184
|
const matchEnd = offset;
|
|
@@ -15273,11 +15189,8 @@
|
|
|
15273
15189
|
el.textContent = innerText;
|
|
15274
15190
|
const beforeNode = document.createTextNode(before);
|
|
15275
15191
|
const afterNode = document.createTextNode("" + after);
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
parent.insertBefore(el, node);
|
|
15279
|
-
parent.insertBefore(afterNode, node);
|
|
15280
|
-
parent.removeChild(node);
|
|
15192
|
+
/** @type {ChildNode} */ node.before(beforeNode, el, afterNode);
|
|
15193
|
+
/** @type {ChildNode} */ node.remove();
|
|
15281
15194
|
const newRange = document.createRange();
|
|
15282
15195
|
newRange.setStart(afterNode, 1);
|
|
15283
15196
|
newRange.collapse(true);
|
|
@@ -15348,12 +15261,12 @@
|
|
|
15348
15261
|
strikethrough: (ctx) => ctx.invoke("editor.strikethrough"),
|
|
15349
15262
|
link: (ctx) => ctx.invoke("linkDialog.show"),
|
|
15350
15263
|
removeFormat: (ctx) => {
|
|
15351
|
-
const editable = ctx.layoutInfo
|
|
15264
|
+
const editable = ctx.layoutInfo?.editable;
|
|
15352
15265
|
if (!editable) return;
|
|
15353
15266
|
editable.focus();
|
|
15354
15267
|
document.execCommand("removeFormat");
|
|
15355
|
-
const sel =
|
|
15356
|
-
if (sel
|
|
15268
|
+
const sel = globalThis.getSelection();
|
|
15269
|
+
if (sel?.rangeCount > 0 && !sel.getRangeAt(0).collapsed) {
|
|
15357
15270
|
const range = sel.getRangeAt(0);
|
|
15358
15271
|
const ancestor = range.commonAncestorContainer;
|
|
15359
15272
|
const root = ancestor.nodeType === 1 ? ancestor : ancestor.parentElement;
|
|
@@ -15411,15 +15324,15 @@
|
|
|
15411
15324
|
const d6 = this.context.on("contextMenu:hide", () => {
|
|
15412
15325
|
this._contextMenuOpen = false;
|
|
15413
15326
|
});
|
|
15414
|
-
const d7 = on(
|
|
15415
|
-
const d8 = on(
|
|
15327
|
+
const d7 = on(globalThis, "scroll", () => this._hide(), { passive: true });
|
|
15328
|
+
const d8 = on(globalThis, "resize", () => this._hide(), { passive: true });
|
|
15416
15329
|
this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8);
|
|
15417
15330
|
return this;
|
|
15418
15331
|
}
|
|
15419
15332
|
destroy() {
|
|
15420
|
-
|
|
15333
|
+
this._el?.remove();
|
|
15421
15334
|
this._el = null;
|
|
15422
|
-
|
|
15335
|
+
this._picker?.remove();
|
|
15423
15336
|
this._picker = null;
|
|
15424
15337
|
this._disposers.forEach((d) => d());
|
|
15425
15338
|
this._disposers = [];
|
|
@@ -15533,15 +15446,15 @@
|
|
|
15533
15446
|
pickerAny._colorInput = colorInput;
|
|
15534
15447
|
}
|
|
15535
15448
|
_openColorPicker(type, anchorBtn) {
|
|
15536
|
-
const sel =
|
|
15537
|
-
if (sel
|
|
15449
|
+
const sel = globalThis.getSelection();
|
|
15450
|
+
if (sel?.rangeCount > 0) this._savedRange = sel.getRangeAt(0).cloneRange();
|
|
15538
15451
|
this._pickerType = type;
|
|
15539
15452
|
const pickerAny = this._picker;
|
|
15540
15453
|
const palette = pickerAny._paletteEl;
|
|
15541
15454
|
const noColorBtn = pickerAny._noColorBtn;
|
|
15542
15455
|
if (type === "hiliteColor") {
|
|
15543
15456
|
if (!palette.contains(noColorBtn)) palette.appendChild(noColorBtn);
|
|
15544
|
-
} else if (palette.contains(noColorBtn))
|
|
15457
|
+
} else if (palette.contains(noColorBtn)) noColorBtn.remove();
|
|
15545
15458
|
/** @type {any} */ this._picker._colorInput.value = type === "foreColor" ? "#000000" : "#ffff00";
|
|
15546
15459
|
this._picker.style.display = "block";
|
|
15547
15460
|
const pw = this._picker.offsetWidth;
|
|
@@ -15550,7 +15463,7 @@
|
|
|
15550
15463
|
let top = toolbarRect.top - ph - 6;
|
|
15551
15464
|
if (top < 8) top = toolbarRect.bottom + 6;
|
|
15552
15465
|
let left = anchorBtn.getBoundingClientRect().left;
|
|
15553
|
-
left = Math.max(8, Math.min(left,
|
|
15466
|
+
left = Math.max(8, Math.min(left, globalThis.innerWidth - pw - 8));
|
|
15554
15467
|
this._picker.style.left = `${left}px`;
|
|
15555
15468
|
this._picker.style.top = `${top}px`;
|
|
15556
15469
|
}
|
|
@@ -15560,10 +15473,10 @@
|
|
|
15560
15473
|
}
|
|
15561
15474
|
/** Restore the saved selection, apply execCommand, update the color strip, then close the picker. */
|
|
15562
15475
|
_applyColor(type, color) {
|
|
15563
|
-
const editable = this.context.layoutInfo
|
|
15476
|
+
const editable = this.context.layoutInfo?.editable;
|
|
15564
15477
|
if (!editable || !this._savedRange) return;
|
|
15565
15478
|
editable.focus();
|
|
15566
|
-
const sel =
|
|
15479
|
+
const sel = globalThis.getSelection();
|
|
15567
15480
|
sel.removeAllRanges();
|
|
15568
15481
|
try {
|
|
15569
15482
|
sel.addRange(this._savedRange.cloneRange());
|
|
@@ -15574,8 +15487,7 @@
|
|
|
15574
15487
|
if (!document.execCommand(cmd, false, color) && cmd === "hiliteColor") document.execCommand("backColor", false, color);
|
|
15575
15488
|
this.context.invoke("editor.afterCommand");
|
|
15576
15489
|
const name = type === "hiliteColor" ? "hiliteColor" : "foreColor";
|
|
15577
|
-
const
|
|
15578
|
-
const strip = btn && btn.querySelector(".an-bubble-color-strip");
|
|
15490
|
+
const strip = (this._el?.querySelector(`[data-name="${name}"]`))?.querySelector(".an-bubble-color-strip");
|
|
15579
15491
|
if (strip) /** @type {HTMLElement} */ strip.style.background = color === "transparent" ? "transparent" : color;
|
|
15580
15492
|
this._closeColorPicker();
|
|
15581
15493
|
this._syncActive();
|
|
@@ -15590,14 +15502,14 @@
|
|
|
15590
15502
|
const gap = 8;
|
|
15591
15503
|
let left = rect.left + rect.width / 2 - bw / 2;
|
|
15592
15504
|
let top = rect.top - bh - gap;
|
|
15593
|
-
left = Math.max(8, Math.min(left,
|
|
15505
|
+
left = Math.max(8, Math.min(left, globalThis.innerWidth - bw - 8));
|
|
15594
15506
|
if (top < 8) top = rect.bottom + gap;
|
|
15595
15507
|
const tableTooltipEl = document.querySelector(".an-table-tooltip");
|
|
15596
15508
|
if (tableTooltipEl && tableTooltipEl.style.display !== "none") {
|
|
15597
15509
|
const ttRect = tableTooltipEl.getBoundingClientRect();
|
|
15598
15510
|
if (top < ttRect.bottom + gap && top + bh > ttRect.top - gap) {
|
|
15599
15511
|
top = rect.bottom + gap;
|
|
15600
|
-
if (top + bh >
|
|
15512
|
+
if (top + bh > globalThis.innerHeight - 8) top = ttRect.bottom + gap;
|
|
15601
15513
|
}
|
|
15602
15514
|
}
|
|
15603
15515
|
el.style.top = `${top}px`;
|
|
@@ -15623,17 +15535,15 @@
|
|
|
15623
15535
|
/** Read the current selection's color and update the color-strip indicators. */
|
|
15624
15536
|
_syncColorStrips() {
|
|
15625
15537
|
if (!this._el) return;
|
|
15626
|
-
const sel =
|
|
15538
|
+
const sel = globalThis.getSelection();
|
|
15627
15539
|
if (!sel || !sel.rangeCount) return;
|
|
15628
15540
|
let node = sel.getRangeAt(0).startContainer;
|
|
15629
15541
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
15630
15542
|
if (!node) return;
|
|
15631
|
-
const cs =
|
|
15632
|
-
const
|
|
15633
|
-
const foreStrip = foreBtn && foreBtn.querySelector(".an-bubble-color-strip");
|
|
15543
|
+
const cs = globalThis.getComputedStyle(node);
|
|
15544
|
+
const foreStrip = this._el.querySelector("[data-name=\"foreColor\"]")?.querySelector(".an-bubble-color-strip");
|
|
15634
15545
|
if (foreStrip) /** @type {HTMLElement} */ foreStrip.style.background = cs.color || "#000000";
|
|
15635
|
-
const
|
|
15636
|
-
const hiliteStrip = hiliteBtn && hiliteBtn.querySelector(".an-bubble-color-strip");
|
|
15546
|
+
const hiliteStrip = this._el.querySelector("[data-name=\"hiliteColor\"]")?.querySelector(".an-bubble-color-strip");
|
|
15637
15547
|
if (hiliteStrip) {
|
|
15638
15548
|
const bg = cs.backgroundColor;
|
|
15639
15549
|
/** @type {HTMLElement} */ hiliteStrip.style.background = !bg || bg === "rgba(0, 0, 0, 0)" || bg === "transparent" ? "transparent" : bg;
|
|
@@ -15644,7 +15554,7 @@
|
|
|
15644
15554
|
this._rafId = requestAnimationFrame(() => {
|
|
15645
15555
|
if (this._contextMenuOpen) return;
|
|
15646
15556
|
if (this._picker && this._picker.style.display !== "none") return;
|
|
15647
|
-
const sel =
|
|
15557
|
+
const sel = globalThis.getSelection();
|
|
15648
15558
|
if (!sel || sel.isCollapsed || !sel.rangeCount) {
|
|
15649
15559
|
this._hide();
|
|
15650
15560
|
return;
|
|
@@ -15667,8 +15577,8 @@
|
|
|
15667
15577
|
}
|
|
15668
15578
|
_onMousedown(e) {
|
|
15669
15579
|
if (!this._visible) return;
|
|
15670
|
-
if (this._el
|
|
15671
|
-
if (this._picker
|
|
15580
|
+
if (this._el?.contains(e.target)) return;
|
|
15581
|
+
if (this._picker?.contains(e.target)) return;
|
|
15672
15582
|
if (this.context.layoutInfo.editable.contains(e.target)) return;
|
|
15673
15583
|
this._hide();
|
|
15674
15584
|
}
|
|
@@ -15753,7 +15663,7 @@
|
|
|
15753
15663
|
}
|
|
15754
15664
|
destroy() {
|
|
15755
15665
|
clearTimeout(this._debounceTimer);
|
|
15756
|
-
|
|
15666
|
+
this._dropdown?.remove();
|
|
15757
15667
|
this._dropdown = null;
|
|
15758
15668
|
this._disposers.forEach((d) => d());
|
|
15759
15669
|
this._disposers = [];
|
|
@@ -15817,8 +15727,8 @@
|
|
|
15817
15727
|
const ddw = dd.offsetWidth;
|
|
15818
15728
|
let top = rect.bottom + 4;
|
|
15819
15729
|
let left = rect.left;
|
|
15820
|
-
if (rect.bottom + ddh + 8 >
|
|
15821
|
-
left = Math.max(8, Math.min(left,
|
|
15730
|
+
if (rect.bottom + ddh + 8 > globalThis.innerHeight) top = rect.top - ddh - 4;
|
|
15731
|
+
left = Math.max(8, Math.min(left, globalThis.innerWidth - ddw - 8));
|
|
15822
15732
|
dd.style.top = `${top}px`;
|
|
15823
15733
|
dd.style.left = `${left}px`;
|
|
15824
15734
|
dd.style.visibility = "";
|
|
@@ -15842,7 +15752,7 @@
|
|
|
15842
15752
|
* collapsed range is reliable at this point but often empty inside async callbacks.
|
|
15843
15753
|
*/
|
|
15844
15754
|
_captureCaretRect() {
|
|
15845
|
-
if (this._triggerNode
|
|
15755
|
+
if (this._triggerNode?.isConnected) try {
|
|
15846
15756
|
const r = document.createRange();
|
|
15847
15757
|
const end = Math.min(this._triggerOffset + 1, this._triggerNode.textContent.length);
|
|
15848
15758
|
r.setStart(this._triggerNode, this._triggerOffset);
|
|
@@ -15853,13 +15763,13 @@
|
|
|
15853
15763
|
return;
|
|
15854
15764
|
}
|
|
15855
15765
|
} catch (_) {}
|
|
15856
|
-
const sel =
|
|
15766
|
+
const sel = globalThis.getSelection();
|
|
15857
15767
|
if (!sel || !sel.rangeCount) return;
|
|
15858
15768
|
const rects = sel.getRangeAt(0).getClientRects();
|
|
15859
15769
|
if (rects.length > 0) this._caretRect = rects[rects.length - 1];
|
|
15860
15770
|
}
|
|
15861
15771
|
_getQueryAtCursor() {
|
|
15862
|
-
const sel =
|
|
15772
|
+
const sel = globalThis.getSelection();
|
|
15863
15773
|
if (!sel || !sel.rangeCount) return null;
|
|
15864
15774
|
const range = sel.getRangeAt(0);
|
|
15865
15775
|
if (!range.collapsed) return null;
|
|
@@ -15916,7 +15826,7 @@
|
|
|
15916
15826
|
}
|
|
15917
15827
|
_onDocClick(e) {
|
|
15918
15828
|
if (!this._open) return;
|
|
15919
|
-
if (this._dropdown
|
|
15829
|
+
if (this._dropdown?.contains(e.target)) return;
|
|
15920
15830
|
this._hideDropdown();
|
|
15921
15831
|
}
|
|
15922
15832
|
_select(index) {
|
|
@@ -15925,7 +15835,7 @@
|
|
|
15925
15835
|
if (this._triggerNode) {
|
|
15926
15836
|
const node = this._triggerNode;
|
|
15927
15837
|
node.textContent = node.textContent.slice(0, this._triggerOffset) + node.textContent.slice(this._triggerOffset + this._cfg.trigger.length + this._query.length);
|
|
15928
|
-
const sel =
|
|
15838
|
+
const sel = globalThis.getSelection();
|
|
15929
15839
|
const range = document.createRange();
|
|
15930
15840
|
range.setStart(node, this._triggerOffset);
|
|
15931
15841
|
range.collapse(true);
|
|
@@ -16028,7 +15938,7 @@
|
|
|
16028
15938
|
register("markdownShortcuts", MarkdownShortcuts);
|
|
16029
15939
|
register("bubbleToolbar", BubbleToolbar);
|
|
16030
15940
|
register("mention", Mention);
|
|
16031
|
-
for (const [name, ModuleClass] of _customModules) register(name, ModuleClass);
|
|
15941
|
+
if (_customModules.size > 0) for (const [name, ModuleClass] of _customModules) register(name, ModuleClass);
|
|
16032
15942
|
}
|
|
16033
15943
|
/**
|
|
16034
15944
|
* Registers and initialises a custom module on this instance.
|
|
@@ -16081,6 +15991,7 @@
|
|
|
16081
15991
|
});
|
|
16082
15992
|
}
|
|
16083
15993
|
_applyGlobalPlugins() {
|
|
15994
|
+
if (_globalPlugins.size === 0) return;
|
|
16084
15995
|
for (const { plugin, options } of _globalPlugins.values()) this._installPlugin(plugin, options);
|
|
16085
15996
|
}
|
|
16086
15997
|
_bindEditorEvents(editable) {
|
|
@@ -16286,23 +16197,27 @@
|
|
|
16286
16197
|
a.style.display = "none";
|
|
16287
16198
|
document.body.appendChild(a);
|
|
16288
16199
|
a.click();
|
|
16289
|
-
|
|
16200
|
+
a.remove();
|
|
16290
16201
|
URL.revokeObjectURL(url);
|
|
16291
16202
|
}
|
|
16292
16203
|
/**
|
|
16293
|
-
* Opens the editor content in a new
|
|
16204
|
+
* Opens the editor content in a new globalThis and triggers the browser print dialog.
|
|
16294
16205
|
* @param {string} [title='']
|
|
16295
16206
|
*/
|
|
16296
16207
|
print(title = "") {
|
|
16297
16208
|
const content = this.getHTML();
|
|
16298
|
-
const
|
|
16299
|
-
const
|
|
16300
|
-
|
|
16301
|
-
w
|
|
16302
|
-
w
|
|
16303
|
-
|
|
16209
|
+
const markup = `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>${(title || "").replace(/[<>&"']/g, (c) => `&#${c.charCodeAt(0)};`)}</title><style>body{font-family:system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;font-size:14px;line-height:1.6;padding:20mm;color:#111827;}ul.an-checklist{list-style:none;padding-left:0;}ul.an-checklist li{padding-left:24px;position:relative;margin:2px 0;}ul.an-checklist li input[type="checkbox"]{position:absolute;left:0;top:3px;}code{background:#f3f4f6;border-radius:3px;padding:.1em .35em;font-family:monospace;}pre{background:#f3f4f6;padding:.75em 1em;border-radius:4px;overflow-x:auto;}table{border-collapse:collapse;}td,th{border:1px solid #d1d5db;padding:4px 8px;}</style></head><body>${content}</body></html>`;
|
|
16210
|
+
const blob = new Blob([markup], { type: "text/html" });
|
|
16211
|
+
const url = URL.createObjectURL(blob);
|
|
16212
|
+
const w = globalThis.open(url, "_blank");
|
|
16213
|
+
if (!w) {
|
|
16214
|
+
URL.revokeObjectURL(url);
|
|
16215
|
+
return;
|
|
16216
|
+
}
|
|
16217
|
+
w.addEventListener("load", () => {
|
|
16304
16218
|
w.print();
|
|
16305
|
-
|
|
16219
|
+
URL.revokeObjectURL(url);
|
|
16220
|
+
});
|
|
16306
16221
|
}
|
|
16307
16222
|
/**
|
|
16308
16223
|
* Sets whether the editor is disabled (readonly).
|
|
@@ -16340,10 +16255,10 @@
|
|
|
16340
16255
|
this._disposers.forEach((d) => d());
|
|
16341
16256
|
this._disposers = [];
|
|
16342
16257
|
const container = this.layoutInfo.container;
|
|
16343
|
-
const wasDark = container
|
|
16344
|
-
if (container
|
|
16258
|
+
const wasDark = container?.classList.contains("an-theme-dark");
|
|
16259
|
+
if (container?.parentNode) {
|
|
16345
16260
|
this.targetEl.style.display = "";
|
|
16346
|
-
container.
|
|
16261
|
+
container.remove();
|
|
16347
16262
|
}
|
|
16348
16263
|
if (wasDark && !document.querySelector(".an-container.an-theme-dark")) document.body.classList.remove("an-theme-dark");
|
|
16349
16264
|
if (typeof this.options.onDestroy === "function") this.options.onDestroy(this);
|
|
@@ -16365,7 +16280,7 @@
|
|
|
16365
16280
|
* Inspired by Summernote's env.js
|
|
16366
16281
|
*/
|
|
16367
16282
|
var userAgent = navigator.userAgent;
|
|
16368
|
-
/Chrome\//.test(userAgent), /Firefox\//.test(userAgent), /^((?!chrome|android).)*safari/i.test(userAgent), /Edg\//.test(userAgent), /Macintosh/.test(userAgent), /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent), "ontouchstart" in
|
|
16283
|
+
/Chrome\//.test(userAgent), /Firefox\//.test(userAgent), /^((?!chrome|android).)*safari/i.test(userAgent), /Edg\//.test(userAgent), /Macintosh/.test(userAgent), /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent), "ontouchstart" in globalThis || navigator.maxTouchPoints, /Macintosh/.test(userAgent);
|
|
16369
16284
|
//#endregion
|
|
16370
16285
|
//#region src/js/index.js
|
|
16371
16286
|
var _originalDefaults = { ...defaultOptions };
|
|
@@ -16473,7 +16388,7 @@
|
|
|
16473
16388
|
return this;
|
|
16474
16389
|
},
|
|
16475
16390
|
/** Library version */
|
|
16476
|
-
version: "1.
|
|
16391
|
+
version: "1.6.2"
|
|
16477
16392
|
};
|
|
16478
16393
|
/**
|
|
16479
16394
|
* @param {string|Element|NodeList|Element[]} selector
|