tinymce-rails 8.9.3 → 8.10.1
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.
- checksums.yaml +4 -4
- data/app/assets/source/tinymce/tinymce.js +274 -219
- data/lib/tinymce/rails/version.rb +2 -2
- data/vendor/assets/javascripts/tinymce/icons/default/icons.js +1 -1
- data/vendor/assets/javascripts/tinymce/models/dom/model.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/advlist/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/themes/silver/theme.js +1 -1
- data/vendor/assets/javascripts/tinymce/tinymce.d.ts +2 -1
- data/vendor/assets/javascripts/tinymce/tinymce.js +3 -3
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0aa0b46f0c60b3f5299265cf18434083cc20c90edca680e7aea3d4a51a7eb845
|
|
4
|
+
data.tar.gz: eea41881902fe912d5802a770b797817b44f6ec21d196ce40c72dc4a2862ddf0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 51ef53c4b01237071b3e711594fe9ed2e3762f8fd0eec78166ad33a2473aae1a197f09ff2c30866b1e354723fc097b52768a04245d828854f43827d364749e3c
|
|
7
|
+
data.tar.gz: 07df40aa209cf71d6e976945167463bc56219b5c8ea6265c9800b5b631f5553a42a0f1ae67f7131c99bedb4ea60e338792018e815c8ca16e3074b96ebd32a8e4
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TinyMCE version 8.
|
|
2
|
+
* TinyMCE version 8.10.1 (2026-10-28)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
(function () {
|
|
@@ -1155,6 +1155,35 @@
|
|
|
1155
1155
|
return isNaN(num) ? Optional.none() : Optional.some(num);
|
|
1156
1156
|
};
|
|
1157
1157
|
|
|
1158
|
+
// Run a function fn after rate ms. If another invocation occurs
|
|
1159
|
+
// during the time it is waiting, update the arguments f will run
|
|
1160
|
+
// with (but keep the current schedule)
|
|
1161
|
+
const adaptable = (fn, rate) => {
|
|
1162
|
+
let timer = null;
|
|
1163
|
+
let args = null;
|
|
1164
|
+
const cancel = () => {
|
|
1165
|
+
if (!isNull(timer)) {
|
|
1166
|
+
clearTimeout(timer);
|
|
1167
|
+
timer = null;
|
|
1168
|
+
args = null;
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
const throttle = (...newArgs) => {
|
|
1172
|
+
args = newArgs;
|
|
1173
|
+
if (isNull(timer)) {
|
|
1174
|
+
timer = setTimeout(() => {
|
|
1175
|
+
const tempArgs = args;
|
|
1176
|
+
timer = null;
|
|
1177
|
+
args = null;
|
|
1178
|
+
fn.apply(null, tempArgs);
|
|
1179
|
+
}, rate);
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
return {
|
|
1183
|
+
cancel,
|
|
1184
|
+
throttle
|
|
1185
|
+
};
|
|
1186
|
+
};
|
|
1158
1187
|
// Run a function fn after rate ms. If another invocation occurs
|
|
1159
1188
|
// during the time it is waiting, ignore it completely.
|
|
1160
1189
|
const first$1 = (fn, rate) => {
|
|
@@ -3374,47 +3403,6 @@
|
|
|
3374
3403
|
}
|
|
3375
3404
|
}
|
|
3376
3405
|
|
|
3377
|
-
const whiteSpaceRegExp = /^[ \t\r\n]*$/;
|
|
3378
|
-
const isWhitespaceText = (text) => whiteSpaceRegExp.test(text);
|
|
3379
|
-
const isZwsp$1 = (text) => {
|
|
3380
|
-
for (const c of text) {
|
|
3381
|
-
if (!isZwsp$2(c)) {
|
|
3382
|
-
return false;
|
|
3383
|
-
}
|
|
3384
|
-
}
|
|
3385
|
-
return true;
|
|
3386
|
-
};
|
|
3387
|
-
// Don't compare other unicode spaces here, as we're only concerned about whitespace the browser would collapse
|
|
3388
|
-
const isCollapsibleWhitespace$1 = (c) => ' \f\t\v'.indexOf(c) !== -1;
|
|
3389
|
-
const isNewLineChar = (c) => c === '\n' || c === '\r';
|
|
3390
|
-
const isNewline = (text, idx) => (idx < text.length && idx >= 0) ? isNewLineChar(text[idx]) : false;
|
|
3391
|
-
// Converts duplicate whitespace to alternating space/nbsps and tabs to spaces
|
|
3392
|
-
const normalize$4 = (text, tabSpaces = 4, isStartOfContent = true, isEndOfContent = true) => {
|
|
3393
|
-
// Replace tabs with a variable amount of spaces
|
|
3394
|
-
// Note: We don't use an actual tab character here, as it only works when in a "whitespace: pre" element,
|
|
3395
|
-
// which will cause other issues, such as trying to type the content will also be treated as being in a pre.
|
|
3396
|
-
const tabSpace = repeat(' ', tabSpaces);
|
|
3397
|
-
const normalizedText = text.replace(/\t/g, tabSpace);
|
|
3398
|
-
const result = foldl(normalizedText, (acc, c) => {
|
|
3399
|
-
// Are we dealing with a char other than some collapsible whitespace or nbsp? if so then just use it as is
|
|
3400
|
-
if (isCollapsibleWhitespace$1(c) || c === nbsp) {
|
|
3401
|
-
// If the previous char is a space, we are at the start or end, or if the next char is a new line char, then we need
|
|
3402
|
-
// to convert the space to a nbsp
|
|
3403
|
-
if (acc.pcIsSpace || (acc.str === '' && isStartOfContent) || (acc.str.length === normalizedText.length - 1 && isEndOfContent) || isNewline(normalizedText, acc.str.length + 1)) {
|
|
3404
|
-
return { pcIsSpace: false, str: acc.str + nbsp };
|
|
3405
|
-
}
|
|
3406
|
-
else {
|
|
3407
|
-
return { pcIsSpace: true, str: acc.str + ' ' };
|
|
3408
|
-
}
|
|
3409
|
-
}
|
|
3410
|
-
else {
|
|
3411
|
-
// Treat newlines as being a space, since we'll need to convert any leading spaces to nsbps
|
|
3412
|
-
return { pcIsSpace: isNewLineChar(c), str: acc.str + c };
|
|
3413
|
-
}
|
|
3414
|
-
}, { pcIsSpace: false, str: '' });
|
|
3415
|
-
return result.str;
|
|
3416
|
-
};
|
|
3417
|
-
|
|
3418
3406
|
const isNodeType = (type) => {
|
|
3419
3407
|
return (node) => {
|
|
3420
3408
|
return !!node && node.nodeType === type;
|
|
@@ -3502,6 +3490,47 @@
|
|
|
3502
3490
|
const ucVideoNodeName = 'uc-video';
|
|
3503
3491
|
const isUcVideo = matchNodeName$1(ucVideoNodeName);
|
|
3504
3492
|
|
|
3493
|
+
const whiteSpaceRegExp = /^[ \t\r\n]*$/;
|
|
3494
|
+
const isWhitespaceText = (text) => whiteSpaceRegExp.test(text);
|
|
3495
|
+
const isZwsp$1 = (text) => {
|
|
3496
|
+
for (const c of text) {
|
|
3497
|
+
if (!isZwsp$2(c)) {
|
|
3498
|
+
return false;
|
|
3499
|
+
}
|
|
3500
|
+
}
|
|
3501
|
+
return true;
|
|
3502
|
+
};
|
|
3503
|
+
// Don't compare other unicode spaces here, as we're only concerned about whitespace the browser would collapse
|
|
3504
|
+
const isCollapsibleWhitespace$1 = (c) => ' \f\t\v'.indexOf(c) !== -1;
|
|
3505
|
+
const isNewLineChar = (c) => c === '\n' || c === '\r';
|
|
3506
|
+
const isNewline = (text, idx) => (idx < text.length && idx >= 0) ? isNewLineChar(text[idx]) : false;
|
|
3507
|
+
// Converts duplicate whitespace to alternating space/nbsps and tabs to spaces
|
|
3508
|
+
const normalize$4 = (text, tabSpaces = 4, isStartOfContent = true, isEndOfContent = true) => {
|
|
3509
|
+
// Replace tabs with a variable amount of spaces
|
|
3510
|
+
// Note: We don't use an actual tab character here, as it only works when in a "whitespace: pre" element,
|
|
3511
|
+
// which will cause other issues, such as trying to type the content will also be treated as being in a pre.
|
|
3512
|
+
const tabSpace = repeat(' ', tabSpaces);
|
|
3513
|
+
const normalizedText = text.replace(/\t/g, tabSpace);
|
|
3514
|
+
const result = foldl(normalizedText, (acc, c) => {
|
|
3515
|
+
// Are we dealing with a char other than some collapsible whitespace or nbsp? if so then just use it as is
|
|
3516
|
+
if (isCollapsibleWhitespace$1(c) || c === nbsp) {
|
|
3517
|
+
// If the previous char is a space, we are at the start or end, or if the next char is a new line char, then we need
|
|
3518
|
+
// to convert the space to a nbsp
|
|
3519
|
+
if (acc.pcIsSpace || (acc.str === '' && isStartOfContent) || (acc.str.length === normalizedText.length - 1 && isEndOfContent) || isNewline(normalizedText, acc.str.length + 1)) {
|
|
3520
|
+
return { pcIsSpace: false, str: acc.str + nbsp };
|
|
3521
|
+
}
|
|
3522
|
+
else {
|
|
3523
|
+
return { pcIsSpace: true, str: acc.str + ' ' };
|
|
3524
|
+
}
|
|
3525
|
+
}
|
|
3526
|
+
else {
|
|
3527
|
+
// Treat newlines as being a space, since we'll need to convert any leading spaces to nsbps
|
|
3528
|
+
return { pcIsSpace: isNewLineChar(c), str: acc.str + c };
|
|
3529
|
+
}
|
|
3530
|
+
}, { pcIsSpace: false, str: '' });
|
|
3531
|
+
return result.str;
|
|
3532
|
+
};
|
|
3533
|
+
|
|
3505
3534
|
const defaultOptionValues = {
|
|
3506
3535
|
skipBogus: true,
|
|
3507
3536
|
includeZwsp: false,
|
|
@@ -13765,6 +13794,12 @@
|
|
|
13765
13794
|
editor.nodeChanged();
|
|
13766
13795
|
};
|
|
13767
13796
|
const showResizeRect = (targetElm) => {
|
|
13797
|
+
// The throttled call can fire after setContent has replaced the target, leaving
|
|
13798
|
+
// handles bound to the zero-sized geometry of a detached element
|
|
13799
|
+
if (!targetElm.isConnected) {
|
|
13800
|
+
hideResizeRect();
|
|
13801
|
+
return;
|
|
13802
|
+
}
|
|
13768
13803
|
unbindResizeHandleEvents();
|
|
13769
13804
|
// Get position and size of target
|
|
13770
13805
|
const position = dom.getPos(targetElm, rootElement);
|
|
@@ -13863,7 +13898,9 @@
|
|
|
13863
13898
|
hideResizeRect(false);
|
|
13864
13899
|
}
|
|
13865
13900
|
};
|
|
13866
|
-
|
|
13901
|
+
// Adaptable so a burst of update requests shows the rect for the most recently
|
|
13902
|
+
// requested element rather than the first, which may since have been detached
|
|
13903
|
+
const throttledShowResizeRect = adaptable(showResizeRect, 0);
|
|
13867
13904
|
const hideResizeRect = (removeSelected = true) => {
|
|
13868
13905
|
throttledShowResizeRect.cancel();
|
|
13869
13906
|
unbindResizeHandleEvents();
|
|
@@ -16532,156 +16569,6 @@
|
|
|
16532
16569
|
};
|
|
16533
16570
|
};
|
|
16534
16571
|
|
|
16535
|
-
const getNormalizedPoint$1 = (container, offset) => {
|
|
16536
|
-
if (isText$b(container)) {
|
|
16537
|
-
return { container, offset };
|
|
16538
|
-
}
|
|
16539
|
-
const node = RangeUtils.getNode(container, offset);
|
|
16540
|
-
if (isText$b(node)) {
|
|
16541
|
-
return {
|
|
16542
|
-
container: node,
|
|
16543
|
-
offset: offset >= container.childNodes.length ? node.data.length : 0
|
|
16544
|
-
};
|
|
16545
|
-
}
|
|
16546
|
-
else if (node.previousSibling && isText$b(node.previousSibling)) {
|
|
16547
|
-
return {
|
|
16548
|
-
container: node.previousSibling,
|
|
16549
|
-
offset: node.previousSibling.data.length
|
|
16550
|
-
};
|
|
16551
|
-
}
|
|
16552
|
-
else if (node.nextSibling && isText$b(node.nextSibling)) {
|
|
16553
|
-
return {
|
|
16554
|
-
container: node.nextSibling,
|
|
16555
|
-
offset: 0
|
|
16556
|
-
};
|
|
16557
|
-
}
|
|
16558
|
-
return { container, offset };
|
|
16559
|
-
};
|
|
16560
|
-
const normalizeRange$1 = (rng) => {
|
|
16561
|
-
const outRng = rng.cloneRange();
|
|
16562
|
-
const rangeStart = getNormalizedPoint$1(rng.startContainer, rng.startOffset);
|
|
16563
|
-
outRng.setStart(rangeStart.container, rangeStart.offset);
|
|
16564
|
-
const rangeEnd = getNormalizedPoint$1(rng.endContainer, rng.endOffset);
|
|
16565
|
-
outRng.setEnd(rangeEnd.container, rangeEnd.offset);
|
|
16566
|
-
return outRng;
|
|
16567
|
-
};
|
|
16568
|
-
|
|
16569
|
-
const DOM$b = DOMUtils.DOM;
|
|
16570
|
-
const defaultMarker = () => DOM$b.create('span', { 'data-mce-type': 'bookmark' });
|
|
16571
|
-
const setupEndPoint = (container, offset, createMarker) => {
|
|
16572
|
-
if (isElement$7(container)) {
|
|
16573
|
-
const offsetNode = createMarker();
|
|
16574
|
-
if (container.hasChildNodes()) {
|
|
16575
|
-
if (offset === container.childNodes.length) {
|
|
16576
|
-
container.appendChild(offsetNode);
|
|
16577
|
-
}
|
|
16578
|
-
else {
|
|
16579
|
-
container.insertBefore(offsetNode, container.childNodes[offset]);
|
|
16580
|
-
}
|
|
16581
|
-
}
|
|
16582
|
-
else {
|
|
16583
|
-
container.appendChild(offsetNode);
|
|
16584
|
-
}
|
|
16585
|
-
return { container: offsetNode, offset: 0 };
|
|
16586
|
-
}
|
|
16587
|
-
else {
|
|
16588
|
-
return { container, offset };
|
|
16589
|
-
}
|
|
16590
|
-
};
|
|
16591
|
-
const restoreEndPoint = (container, offset) => {
|
|
16592
|
-
const nodeIndex = (container) => {
|
|
16593
|
-
let node = container.parentNode?.firstChild;
|
|
16594
|
-
let idx = 0;
|
|
16595
|
-
while (node) {
|
|
16596
|
-
if (node === container) {
|
|
16597
|
-
return idx;
|
|
16598
|
-
}
|
|
16599
|
-
// Skip data-mce-type=bookmark nodes
|
|
16600
|
-
if (!isElement$7(node) || node.getAttribute('data-mce-type') !== 'bookmark') {
|
|
16601
|
-
idx++;
|
|
16602
|
-
}
|
|
16603
|
-
node = node.nextSibling;
|
|
16604
|
-
}
|
|
16605
|
-
return -1;
|
|
16606
|
-
};
|
|
16607
|
-
if (isElement$7(container) && isNonNullable(container.parentNode)) {
|
|
16608
|
-
const node = container;
|
|
16609
|
-
offset = nodeIndex(container);
|
|
16610
|
-
container = container.parentNode;
|
|
16611
|
-
DOM$b.remove(node);
|
|
16612
|
-
if (!container.hasChildNodes() && DOM$b.isBlock(container)) {
|
|
16613
|
-
container.appendChild(DOM$b.create('br'));
|
|
16614
|
-
}
|
|
16615
|
-
}
|
|
16616
|
-
return { container, offset };
|
|
16617
|
-
};
|
|
16618
|
-
const createNormalizedRange = (startContainer, startOffset, endContainer, endOffset) => {
|
|
16619
|
-
const rng = DOM$b.createRng();
|
|
16620
|
-
rng.setStart(startContainer, startOffset);
|
|
16621
|
-
rng.setEnd(endContainer, endOffset);
|
|
16622
|
-
return normalizeRange$1(rng);
|
|
16623
|
-
};
|
|
16624
|
-
/**
|
|
16625
|
-
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
|
|
16626
|
-
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
|
|
16627
|
-
* added to them since they can be restored after a dom operation.
|
|
16628
|
-
*
|
|
16629
|
-
* So this: <p><b>|</b><b>|</b></p>
|
|
16630
|
-
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
|
16631
|
-
*/
|
|
16632
|
-
const createBookmark = (rng, createMarker = defaultMarker) => {
|
|
16633
|
-
const { container: startContainer, offset: startOffset } = setupEndPoint(rng.startContainer, rng.startOffset, createMarker);
|
|
16634
|
-
if (rng.collapsed) {
|
|
16635
|
-
return { startContainer, startOffset };
|
|
16636
|
-
}
|
|
16637
|
-
else {
|
|
16638
|
-
const { container: endContainer, offset: endOffset } = setupEndPoint(rng.endContainer, rng.endOffset, createMarker);
|
|
16639
|
-
return { startContainer, startOffset, endContainer, endOffset };
|
|
16640
|
-
}
|
|
16641
|
-
};
|
|
16642
|
-
const resolveBookmark = (bookmark) => {
|
|
16643
|
-
const { container: startContainer, offset: startOffset } = restoreEndPoint(bookmark.startContainer, bookmark.startOffset);
|
|
16644
|
-
if (!isUndefined(bookmark.endContainer) && !isUndefined(bookmark.endOffset)) {
|
|
16645
|
-
const { container: endContainer, offset: endOffset } = restoreEndPoint(bookmark.endContainer, bookmark.endOffset);
|
|
16646
|
-
return createNormalizedRange(startContainer, startOffset, endContainer, endOffset);
|
|
16647
|
-
}
|
|
16648
|
-
else {
|
|
16649
|
-
return createNormalizedRange(startContainer, startOffset, startContainer, startOffset);
|
|
16650
|
-
}
|
|
16651
|
-
};
|
|
16652
|
-
|
|
16653
|
-
const applyStyles = (dom, elm, format, vars) => {
|
|
16654
|
-
Tools.each(format.styles, (value, name) => {
|
|
16655
|
-
dom.setStyle(elm, name, replaceVars(value, vars));
|
|
16656
|
-
});
|
|
16657
|
-
// Needed for the WebKit span spam bug
|
|
16658
|
-
// TODO: Remove this once WebKit/Blink fixes this
|
|
16659
|
-
if (format.styles) {
|
|
16660
|
-
const styleVal = dom.getAttrib(elm, 'style');
|
|
16661
|
-
if (styleVal) {
|
|
16662
|
-
dom.setAttrib(elm, 'data-mce-style', styleVal);
|
|
16663
|
-
}
|
|
16664
|
-
}
|
|
16665
|
-
};
|
|
16666
|
-
const setElementFormat = (ed, elm, fmt, vars, node) => {
|
|
16667
|
-
const dom = ed.dom;
|
|
16668
|
-
if (isFunction(fmt.onformat)) {
|
|
16669
|
-
fmt.onformat(elm, fmt, vars, node);
|
|
16670
|
-
}
|
|
16671
|
-
applyStyles(dom, elm, fmt, vars);
|
|
16672
|
-
Tools.each(fmt.attributes, (value, name) => {
|
|
16673
|
-
dom.setAttrib(elm, name, replaceVars(value, vars));
|
|
16674
|
-
});
|
|
16675
|
-
Tools.each(fmt.classes, (value) => {
|
|
16676
|
-
const newValue = replaceVars(value, vars);
|
|
16677
|
-
if (!dom.hasClass(elm, newValue)) {
|
|
16678
|
-
dom.addClass(elm, newValue);
|
|
16679
|
-
}
|
|
16680
|
-
});
|
|
16681
|
-
};
|
|
16682
|
-
|
|
16683
|
-
const isApplyFormat = (format) => !isArray$1(format.attributes) && !isArray$1(format.styles);
|
|
16684
|
-
|
|
16685
16572
|
const isEq$3 = isEq$5;
|
|
16686
16573
|
const matchesUnInheritedFormatSelector = (ed, node, name) => {
|
|
16687
16574
|
const formatList = ed.formatter.get(name);
|
|
@@ -16935,14 +16822,18 @@
|
|
|
16935
16822
|
selection.setRng(rng);
|
|
16936
16823
|
}
|
|
16937
16824
|
};
|
|
16825
|
+
const isAdjacent = (node, sibling) => node.nextSibling === sibling || node.previousSibling === sibling;
|
|
16826
|
+
const isCaretContainerNodeAdjacentToSelection = (node, startContainer, endContainer) => node === startContainer || node === endContainer || isAdjacent(node, startContainer) || isAdjacent(node, endContainer);
|
|
16938
16827
|
// Removes the caret container for the specified node or all on the current document
|
|
16939
16828
|
const removeCaretContainer = (editor, node, moveCaret) => {
|
|
16940
16829
|
const dom = editor.dom, selection = editor.selection;
|
|
16941
16830
|
if (!node) {
|
|
16942
16831
|
node = getParentCaretContainer(editor.getBody(), selection.getStart());
|
|
16943
16832
|
if (!node) {
|
|
16833
|
+
const startContainer = editor.selection.getRng().startContainer;
|
|
16834
|
+
const endContainer = editor.selection.getRng().endContainer;
|
|
16944
16835
|
while ((node = dom.get(CARET_ID))) {
|
|
16945
|
-
removeCaretContainerNode(editor, node,
|
|
16836
|
+
removeCaretContainerNode(editor, node, isCaretContainerNodeAdjacentToSelection(node, startContainer, endContainer));
|
|
16946
16837
|
}
|
|
16947
16838
|
}
|
|
16948
16839
|
}
|
|
@@ -17145,9 +17036,9 @@
|
|
|
17145
17036
|
}
|
|
17146
17037
|
}
|
|
17147
17038
|
};
|
|
17148
|
-
const disableCaretContainer = (editor, keyCode
|
|
17039
|
+
const disableCaretContainer = (editor, keyCode) => {
|
|
17149
17040
|
const selection = editor.selection, body = editor.getBody();
|
|
17150
|
-
removeCaretContainer(editor, null,
|
|
17041
|
+
removeCaretContainer(editor, null, false);
|
|
17151
17042
|
// Remove caret container if it's empty
|
|
17152
17043
|
if ((keyCode === 8 || keyCode === 46) && selection.isCollapsed() && selection.getStart().innerHTML === ZWSP) {
|
|
17153
17044
|
removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
|
|
@@ -17157,10 +17048,9 @@
|
|
|
17157
17048
|
removeCaretContainer(editor, getParentCaretContainer(body, selection.getStart()), true);
|
|
17158
17049
|
}
|
|
17159
17050
|
};
|
|
17160
|
-
const endsWithNbsp = (element) => isText$b(element) && endsWith(element.data, nbsp);
|
|
17161
17051
|
const setup$B = (editor) => {
|
|
17162
17052
|
editor.on('mouseup keydown', (e) => {
|
|
17163
|
-
disableCaretContainer(editor, e.keyCode
|
|
17053
|
+
disableCaretContainer(editor, e.keyCode);
|
|
17164
17054
|
});
|
|
17165
17055
|
};
|
|
17166
17056
|
const createCaretFormat = (formatNodes) => {
|
|
@@ -17187,6 +17077,156 @@
|
|
|
17187
17077
|
return has$2(inlineElements, name(element)) && !isCaretNode(element.dom) && !isBogus$1(element.dom);
|
|
17188
17078
|
};
|
|
17189
17079
|
|
|
17080
|
+
const getNormalizedPoint$1 = (container, offset) => {
|
|
17081
|
+
if (isText$b(container)) {
|
|
17082
|
+
return { container, offset };
|
|
17083
|
+
}
|
|
17084
|
+
const node = RangeUtils.getNode(container, offset);
|
|
17085
|
+
if (isText$b(node)) {
|
|
17086
|
+
return {
|
|
17087
|
+
container: node,
|
|
17088
|
+
offset: offset >= container.childNodes.length ? node.data.length : 0
|
|
17089
|
+
};
|
|
17090
|
+
}
|
|
17091
|
+
else if (node.previousSibling && isText$b(node.previousSibling)) {
|
|
17092
|
+
return {
|
|
17093
|
+
container: node.previousSibling,
|
|
17094
|
+
offset: node.previousSibling.data.length
|
|
17095
|
+
};
|
|
17096
|
+
}
|
|
17097
|
+
else if (node.nextSibling && isText$b(node.nextSibling)) {
|
|
17098
|
+
return {
|
|
17099
|
+
container: node.nextSibling,
|
|
17100
|
+
offset: 0
|
|
17101
|
+
};
|
|
17102
|
+
}
|
|
17103
|
+
return { container, offset };
|
|
17104
|
+
};
|
|
17105
|
+
const normalizeRange$1 = (rng) => {
|
|
17106
|
+
const outRng = rng.cloneRange();
|
|
17107
|
+
const rangeStart = getNormalizedPoint$1(rng.startContainer, rng.startOffset);
|
|
17108
|
+
outRng.setStart(rangeStart.container, rangeStart.offset);
|
|
17109
|
+
const rangeEnd = getNormalizedPoint$1(rng.endContainer, rng.endOffset);
|
|
17110
|
+
outRng.setEnd(rangeEnd.container, rangeEnd.offset);
|
|
17111
|
+
return outRng;
|
|
17112
|
+
};
|
|
17113
|
+
|
|
17114
|
+
const DOM$b = DOMUtils.DOM;
|
|
17115
|
+
const defaultMarker = () => DOM$b.create('span', { 'data-mce-type': 'bookmark' });
|
|
17116
|
+
const setupEndPoint = (container, offset, createMarker) => {
|
|
17117
|
+
if (isElement$7(container)) {
|
|
17118
|
+
const offsetNode = createMarker();
|
|
17119
|
+
if (container.hasChildNodes()) {
|
|
17120
|
+
if (offset === container.childNodes.length) {
|
|
17121
|
+
container.appendChild(offsetNode);
|
|
17122
|
+
}
|
|
17123
|
+
else {
|
|
17124
|
+
container.insertBefore(offsetNode, container.childNodes[offset]);
|
|
17125
|
+
}
|
|
17126
|
+
}
|
|
17127
|
+
else {
|
|
17128
|
+
container.appendChild(offsetNode);
|
|
17129
|
+
}
|
|
17130
|
+
return { container: offsetNode, offset: 0 };
|
|
17131
|
+
}
|
|
17132
|
+
else {
|
|
17133
|
+
return { container, offset };
|
|
17134
|
+
}
|
|
17135
|
+
};
|
|
17136
|
+
const restoreEndPoint = (container, offset) => {
|
|
17137
|
+
const nodeIndex = (container) => {
|
|
17138
|
+
let node = container.parentNode?.firstChild;
|
|
17139
|
+
let idx = 0;
|
|
17140
|
+
while (node) {
|
|
17141
|
+
if (node === container) {
|
|
17142
|
+
return idx;
|
|
17143
|
+
}
|
|
17144
|
+
// Skip data-mce-type=bookmark nodes
|
|
17145
|
+
if (!isElement$7(node) || node.getAttribute('data-mce-type') !== 'bookmark') {
|
|
17146
|
+
idx++;
|
|
17147
|
+
}
|
|
17148
|
+
node = node.nextSibling;
|
|
17149
|
+
}
|
|
17150
|
+
return -1;
|
|
17151
|
+
};
|
|
17152
|
+
if (isElement$7(container) && isNonNullable(container.parentNode)) {
|
|
17153
|
+
const node = container;
|
|
17154
|
+
offset = nodeIndex(container);
|
|
17155
|
+
container = container.parentNode;
|
|
17156
|
+
DOM$b.remove(node);
|
|
17157
|
+
if (!container.hasChildNodes() && DOM$b.isBlock(container)) {
|
|
17158
|
+
container.appendChild(DOM$b.create('br'));
|
|
17159
|
+
}
|
|
17160
|
+
}
|
|
17161
|
+
return { container, offset };
|
|
17162
|
+
};
|
|
17163
|
+
const createNormalizedRange = (startContainer, startOffset, endContainer, endOffset) => {
|
|
17164
|
+
const rng = DOM$b.createRng();
|
|
17165
|
+
rng.setStart(startContainer, startOffset);
|
|
17166
|
+
rng.setEnd(endContainer, endOffset);
|
|
17167
|
+
return normalizeRange$1(rng);
|
|
17168
|
+
};
|
|
17169
|
+
/**
|
|
17170
|
+
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
|
|
17171
|
+
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
|
|
17172
|
+
* added to them since they can be restored after a dom operation.
|
|
17173
|
+
*
|
|
17174
|
+
* So this: <p><b>|</b><b>|</b></p>
|
|
17175
|
+
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
|
17176
|
+
*/
|
|
17177
|
+
const createBookmark = (rng, createMarker = defaultMarker) => {
|
|
17178
|
+
const { container: startContainer, offset: startOffset } = setupEndPoint(rng.startContainer, rng.startOffset, createMarker);
|
|
17179
|
+
if (rng.collapsed) {
|
|
17180
|
+
return { startContainer, startOffset };
|
|
17181
|
+
}
|
|
17182
|
+
else {
|
|
17183
|
+
const { container: endContainer, offset: endOffset } = setupEndPoint(rng.endContainer, rng.endOffset, createMarker);
|
|
17184
|
+
return { startContainer, startOffset, endContainer, endOffset };
|
|
17185
|
+
}
|
|
17186
|
+
};
|
|
17187
|
+
const resolveBookmark = (bookmark) => {
|
|
17188
|
+
const { container: startContainer, offset: startOffset } = restoreEndPoint(bookmark.startContainer, bookmark.startOffset);
|
|
17189
|
+
if (!isUndefined(bookmark.endContainer) && !isUndefined(bookmark.endOffset)) {
|
|
17190
|
+
const { container: endContainer, offset: endOffset } = restoreEndPoint(bookmark.endContainer, bookmark.endOffset);
|
|
17191
|
+
return createNormalizedRange(startContainer, startOffset, endContainer, endOffset);
|
|
17192
|
+
}
|
|
17193
|
+
else {
|
|
17194
|
+
return createNormalizedRange(startContainer, startOffset, startContainer, startOffset);
|
|
17195
|
+
}
|
|
17196
|
+
};
|
|
17197
|
+
|
|
17198
|
+
const applyStyles = (dom, elm, format, vars) => {
|
|
17199
|
+
Tools.each(format.styles, (value, name) => {
|
|
17200
|
+
dom.setStyle(elm, name, replaceVars(value, vars));
|
|
17201
|
+
});
|
|
17202
|
+
// Needed for the WebKit span spam bug
|
|
17203
|
+
// TODO: Remove this once WebKit/Blink fixes this
|
|
17204
|
+
if (format.styles) {
|
|
17205
|
+
const styleVal = dom.getAttrib(elm, 'style');
|
|
17206
|
+
if (styleVal) {
|
|
17207
|
+
dom.setAttrib(elm, 'data-mce-style', styleVal);
|
|
17208
|
+
}
|
|
17209
|
+
}
|
|
17210
|
+
};
|
|
17211
|
+
const setElementFormat = (ed, elm, fmt, vars, node) => {
|
|
17212
|
+
const dom = ed.dom;
|
|
17213
|
+
if (isFunction(fmt.onformat)) {
|
|
17214
|
+
fmt.onformat(elm, fmt, vars, node);
|
|
17215
|
+
}
|
|
17216
|
+
applyStyles(dom, elm, fmt, vars);
|
|
17217
|
+
Tools.each(fmt.attributes, (value, name) => {
|
|
17218
|
+
dom.setAttrib(elm, name, replaceVars(value, vars));
|
|
17219
|
+
});
|
|
17220
|
+
Tools.each(fmt.classes, (value) => {
|
|
17221
|
+
const newValue = replaceVars(value, vars);
|
|
17222
|
+
if (!dom.hasClass(elm, newValue)) {
|
|
17223
|
+
dom.addClass(elm, newValue);
|
|
17224
|
+
}
|
|
17225
|
+
});
|
|
17226
|
+
};
|
|
17227
|
+
|
|
17228
|
+
const isApplyFormat = (format) => !isArray$1(format.attributes) && !isArray$1(format.styles);
|
|
17229
|
+
|
|
17190
17230
|
const listItemStyles = ['fontWeight', 'fontStyle', 'color', 'fontSize', 'fontFamily'];
|
|
17191
17231
|
const hasListStyles = (fmt) => isObject(fmt.styles) && exists(keys(fmt.styles), (name) => contains$2(listItemStyles, name));
|
|
17192
17232
|
const findExpandedListItemFormat = (formats) => find$2(formats, (fmt) => isInlineFormat(fmt) && fmt.inline === 'span' && hasListStyles(fmt));
|
|
@@ -22837,6 +22877,18 @@
|
|
|
22837
22877
|
}
|
|
22838
22878
|
selection.setRng(rng);
|
|
22839
22879
|
};
|
|
22880
|
+
const isWholeBlockContentInInlineFormat = (editor, rng) => {
|
|
22881
|
+
const dom = editor.dom;
|
|
22882
|
+
const ancestor = rng.commonAncestorContainer;
|
|
22883
|
+
const elm = isText$b(ancestor) ? ancestor.parentNode : ancestor;
|
|
22884
|
+
if (!isElement$7(elm) || !dom.isEditable(elm) || !isFormatElement(editor, SugarElement.fromDom(elm))) {
|
|
22885
|
+
return false;
|
|
22886
|
+
}
|
|
22887
|
+
const block = dom.getParent(elm, dom.isBlock);
|
|
22888
|
+
return isNonNullable(block)
|
|
22889
|
+
&& prevPosition(block, CaretPosition.fromRangeStart(rng)).isNone()
|
|
22890
|
+
&& nextPosition(block, CaretPosition.fromRangeEnd(rng)).isNone();
|
|
22891
|
+
};
|
|
22840
22892
|
const deleteSelectedContent = (editor) => {
|
|
22841
22893
|
const dom = editor.dom;
|
|
22842
22894
|
// Fix for #2595 seems that delete removes one extra character on
|
|
@@ -22850,8 +22902,9 @@
|
|
|
22850
22902
|
deleteCellContents(editor, rng, SugarElement.fromDom(startCell));
|
|
22851
22903
|
// TINY-9193: If the selection is over the whole text node in an element then Firefox incorrectly moves the caret to the previous line
|
|
22852
22904
|
// TINY-11953: If the selection is over the whole anchor node, then Chrome incorrectly removes parent node alongside with it's child - anchor
|
|
22905
|
+
// TINY-11317: If the whole block content is selected inside a common inline format element, native delete removes the format element
|
|
22853
22906
|
}
|
|
22854
|
-
else if (isSelectionOverWholeAnchor(rng) || isSelectionOverWholeTextNode(rng)) {
|
|
22907
|
+
else if (isSelectionOverWholeAnchor(rng) || isSelectionOverWholeTextNode(rng) || isWholeBlockContentInInlineFormat(editor, rng)) {
|
|
22855
22908
|
rng.deleteContents();
|
|
22856
22909
|
}
|
|
22857
22910
|
else {
|
|
@@ -28952,6 +29005,16 @@
|
|
|
28952
29005
|
}
|
|
28953
29006
|
};
|
|
28954
29007
|
|
|
29008
|
+
const clearShadowingItemStyles = (editor) => {
|
|
29009
|
+
each$e(getSelectedListItems(editor), (item) => {
|
|
29010
|
+
const styleType = editor.dom.getStyle(item, 'list-style-type');
|
|
29011
|
+
// Keep none intact as TinyMCE uses it for nested lists
|
|
29012
|
+
if (isNonNullable(styleType) && styleType !== 'none') {
|
|
29013
|
+
editor.dom.setStyle(item, 'list-style-type', '');
|
|
29014
|
+
}
|
|
29015
|
+
});
|
|
29016
|
+
};
|
|
29017
|
+
|
|
28955
29018
|
const updateListStyle = (dom, el, detail) => {
|
|
28956
29019
|
const type = detail['list-style-type'] ? detail['list-style-type'] : null;
|
|
28957
29020
|
dom.setStyle(el, 'list-style-type', type);
|
|
@@ -29286,6 +29349,7 @@
|
|
|
29286
29349
|
else {
|
|
29287
29350
|
toggleSingleList(editor, parentList, listName, detail);
|
|
29288
29351
|
}
|
|
29352
|
+
clearShadowingItemStyles(editor);
|
|
29289
29353
|
};
|
|
29290
29354
|
|
|
29291
29355
|
const findNextCaretContainer = (editor, rng, isForward, root) => {
|
|
@@ -37597,16 +37661,6 @@
|
|
|
37597
37661
|
}
|
|
37598
37662
|
}, true);
|
|
37599
37663
|
};
|
|
37600
|
-
/**
|
|
37601
|
-
* Forces Gecko to render a broken image icon if it fails to load an image.
|
|
37602
|
-
*/
|
|
37603
|
-
const showBrokenImageIcon = () => {
|
|
37604
|
-
editor.contentStyles.push('img:-moz-broken {' +
|
|
37605
|
-
'-moz-force-broken-image-icon:1;' +
|
|
37606
|
-
'min-width:24px;' +
|
|
37607
|
-
'min-height:24px' +
|
|
37608
|
-
'}');
|
|
37609
|
-
};
|
|
37610
37664
|
/**
|
|
37611
37665
|
* iOS has a bug where it's impossible to type if the document has a touchstart event
|
|
37612
37666
|
* bound and the user touches the document while having the on screen keyboard visible.
|
|
@@ -37783,8 +37837,8 @@
|
|
|
37783
37837
|
const clickAfterEl = (clientX, clientY, el) => get$c(getClientRects([el.dom]), 0).exists((rect) => clientX >= rect.right && clientY >= rect.top && clientY <= rect.bottom);
|
|
37784
37838
|
const selectPos = (editor, e, pos) => {
|
|
37785
37839
|
e.preventDefault();
|
|
37786
|
-
editor.focus();
|
|
37787
37840
|
editor.selection.setRng(pos.toRange());
|
|
37841
|
+
editor.focus();
|
|
37788
37842
|
};
|
|
37789
37843
|
/**
|
|
37790
37844
|
* In Chrome in a `LI` that contains a block element and where the first child is an inline element
|
|
@@ -37792,7 +37846,7 @@
|
|
|
37792
37846
|
* issue: https://issues.chromium.org/issues/40767343
|
|
37793
37847
|
**/
|
|
37794
37848
|
const fixInLISelection = () => {
|
|
37795
|
-
editor.on('
|
|
37849
|
+
editor.on('click', (e) => {
|
|
37796
37850
|
const target = SugarElement.fromDom(e.target);
|
|
37797
37851
|
if (isListItem$2(target)) {
|
|
37798
37852
|
firstBlockChildOrNewLine(target).fold(() => {
|
|
@@ -37836,7 +37890,6 @@
|
|
|
37836
37890
|
if (isGecko) {
|
|
37837
37891
|
focusBody();
|
|
37838
37892
|
setGeckoEditingOptions();
|
|
37839
|
-
showBrokenImageIcon();
|
|
37840
37893
|
blockCmdArrowNavigation();
|
|
37841
37894
|
}
|
|
37842
37895
|
};
|
|
@@ -37880,7 +37933,6 @@
|
|
|
37880
37933
|
removeStylesWhenDeletingAcrossBlockElements();
|
|
37881
37934
|
setGeckoEditingOptions();
|
|
37882
37935
|
addBrAfterLastLinks();
|
|
37883
|
-
showBrokenImageIcon();
|
|
37884
37936
|
blockCmdArrowNavigation();
|
|
37885
37937
|
disableBackspaceIntoATable();
|
|
37886
37938
|
}
|
|
@@ -38399,7 +38451,7 @@
|
|
|
38399
38451
|
id: id + '_ifr',
|
|
38400
38452
|
frameBorder: '0',
|
|
38401
38453
|
allowTransparency: 'true',
|
|
38402
|
-
|
|
38454
|
+
title
|
|
38403
38455
|
});
|
|
38404
38456
|
add$2(iframe, 'tox-edit-area__iframe');
|
|
38405
38457
|
return iframe;
|
|
@@ -38415,12 +38467,15 @@
|
|
|
38415
38467
|
const bodyId = getBodyId(editor);
|
|
38416
38468
|
const bodyClass = getBodyClass(editor);
|
|
38417
38469
|
const translatedAriaText = editor.translate(getIframeAriaText(editor));
|
|
38418
|
-
|
|
38470
|
+
// TINYMCE-13100: VoiceOver does not read the iframe title, so the body is labelled
|
|
38471
|
+
// for it. VoiceOver only runs on macOS, and elsewhere the title is announced.
|
|
38472
|
+
// The role goes with it, since aria-label on a generic role is a violation.
|
|
38473
|
+
const iframeBodyAriaAttrs = Env.os.isMacOS() || Env.os.isiOS() ? `role="textbox" aria-multiline="true" aria-label="${translatedAriaText}"` : '';
|
|
38419
38474
|
if (getContentSecurityPolicy(editor)) {
|
|
38420
38475
|
iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + getContentSecurityPolicy(editor) + '" />';
|
|
38421
38476
|
}
|
|
38422
38477
|
iframeHTML += '</head>' +
|
|
38423
|
-
`<body id="${bodyId}" class="mce-content-body ${bodyClass}" data-id="${editor.id}" ${
|
|
38478
|
+
`<body id="${bodyId}" class="mce-content-body ${bodyClass}" data-id="${editor.id}" ${iframeBodyAriaAttrs}>` +
|
|
38424
38479
|
'<br>' +
|
|
38425
38480
|
'</body></html>';
|
|
38426
38481
|
return iframeHTML;
|
|
@@ -39725,7 +39780,7 @@
|
|
|
39725
39780
|
return false;
|
|
39726
39781
|
}
|
|
39727
39782
|
if (lowerCaseCommand !== 'mcefocus') {
|
|
39728
|
-
if (!/^(mceAddUndoLevel|mceEndUndoLevel)$/i.test(lowerCaseCommand) && !skipFocus) {
|
|
39783
|
+
if (!/^(mceAddUndoLevel|mceEndUndoLevel|toggleview)$/i.test(lowerCaseCommand) && !skipFocus) {
|
|
39729
39784
|
editor.focus();
|
|
39730
39785
|
}
|
|
39731
39786
|
else {
|
|
@@ -42102,14 +42157,14 @@
|
|
|
42102
42157
|
* @property minorVersion
|
|
42103
42158
|
* @type String
|
|
42104
42159
|
*/
|
|
42105
|
-
minorVersion: '
|
|
42160
|
+
minorVersion: '10.1',
|
|
42106
42161
|
/**
|
|
42107
42162
|
* Release date of TinyMCE build.
|
|
42108
42163
|
*
|
|
42109
42164
|
* @property releaseDate
|
|
42110
42165
|
* @type String
|
|
42111
42166
|
*/
|
|
42112
|
-
releaseDate: '2026-10-
|
|
42167
|
+
releaseDate: '2026-10-28',
|
|
42113
42168
|
/**
|
|
42114
42169
|
* Collection of language pack data.
|
|
42115
42170
|
*
|