@limetech/lime-elements 37.77.0 → 37.78.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.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/{3d-tilt-hover-effect-f64da0a8.js → 3d-tilt-hover-effect-ef81ae4c.js} +2 -6
- package/dist/cjs/3d-tilt-hover-effect-ef81ae4c.js.map +1 -0
- package/dist/cjs/lime-elements.cjs.js +1 -1
- package/dist/cjs/limel-3d-hover-effect-glow.cjs.entry.js +21 -0
- package/dist/cjs/limel-3d-hover-effect-glow.cjs.entry.js.map +1 -0
- package/dist/cjs/limel-card.cjs.entry.js +3 -3
- package/dist/cjs/limel-card.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-info-tile.cjs.entry.js +3 -3
- package/dist/cjs/limel-info-tile.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-picker.cjs.entry.js +20 -1
- package/dist/cjs/limel-picker.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +341 -116
- package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js.map +1 -1
- package/dist/cjs/limel-shortcut.cjs.entry.js +9 -6
- package/dist/cjs/limel-shortcut.cjs.entry.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/3d-hover-effect-glow/3d-hover-effect-glow.css +18 -0
- package/dist/collection/components/3d-hover-effect-glow/3d-hover-effect-glow.js +34 -0
- package/dist/collection/components/3d-hover-effect-glow/3d-hover-effect-glow.js.map +1 -0
- package/dist/collection/components/card/card.css +9 -16
- package/dist/collection/components/card/card.js +1 -1
- package/dist/collection/components/card/card.js.map +1 -1
- package/dist/collection/components/info-tile/info-tile.css +9 -16
- package/dist/collection/components/info-tile/info-tile.js +1 -1
- package/dist/collection/components/info-tile/info-tile.js.map +1 -1
- package/dist/collection/components/picker/picker.js +50 -3
- package/dist/collection/components/picker/picker.js.map +1 -1
- package/dist/collection/components/shortcut/shortcut.css +65 -34
- package/dist/collection/components/shortcut/shortcut.js +9 -6
- package/dist/collection/components/shortcut/shortcut.js.map +1 -1
- package/dist/collection/style/mixins.scss +9 -36
- package/dist/collection/util/3d-tilt-hover-effect.js +1 -5
- package/dist/collection/util/3d-tilt-hover-effect.js.map +1 -1
- package/dist/esm/{3d-tilt-hover-effect-a76fcd43.js → 3d-tilt-hover-effect-05648b3c.js} +2 -6
- package/dist/esm/3d-tilt-hover-effect-05648b3c.js.map +1 -0
- package/dist/esm/lime-elements.js +1 -1
- package/dist/esm/limel-3d-hover-effect-glow.entry.js +17 -0
- package/dist/esm/limel-3d-hover-effect-glow.entry.js.map +1 -0
- package/dist/esm/limel-card.entry.js +3 -3
- package/dist/esm/limel-card.entry.js.map +1 -1
- package/dist/esm/limel-info-tile.entry.js +3 -3
- package/dist/esm/limel-info-tile.entry.js.map +1 -1
- package/dist/esm/limel-picker.entry.js +20 -1
- package/dist/esm/limel-picker.entry.js.map +1 -1
- package/dist/esm/limel-prosemirror-adapter.entry.js +341 -116
- package/dist/esm/limel-prosemirror-adapter.entry.js.map +1 -1
- package/dist/esm/limel-shortcut.entry.js +10 -7
- package/dist/esm/limel-shortcut.entry.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/lime-elements/lime-elements.esm.js +1 -1
- package/dist/lime-elements/lime-elements.esm.js.map +1 -1
- package/dist/lime-elements/p-85ffcf55.entry.js +2 -0
- package/dist/lime-elements/p-85ffcf55.entry.js.map +1 -0
- package/dist/lime-elements/p-8e7788a1.entry.js +2 -0
- package/dist/lime-elements/p-8e7788a1.entry.js.map +1 -0
- package/dist/lime-elements/p-ac69fa25.entry.js +2 -0
- package/dist/lime-elements/p-ac69fa25.entry.js.map +1 -0
- package/dist/lime-elements/p-b66faa7b.entry.js +2 -0
- package/dist/lime-elements/p-b66faa7b.entry.js.map +1 -0
- package/dist/lime-elements/{p-05c10bed.entry.js → p-c7d07d05.entry.js} +2 -2
- package/dist/lime-elements/p-c7d07d05.entry.js.map +1 -0
- package/dist/lime-elements/p-d39c198b.entry.js +2 -0
- package/dist/lime-elements/p-d39c198b.entry.js.map +1 -0
- package/dist/lime-elements/{p-23bc6de0.js → p-e1e25236.js} +1 -1
- package/dist/lime-elements/p-e1e25236.js.map +1 -0
- package/dist/lime-elements/style/mixins.scss +9 -36
- package/dist/scss/mixins.scss +9 -36
- package/dist/types/components/3d-hover-effect-glow/3d-hover-effect-glow.d.ts +19 -0
- package/dist/types/components/picker/picker.d.ts +14 -2
- package/dist/types/components/shortcut/shortcut.d.ts +5 -1
- package/dist/types/components.d.ts +70 -5
- package/dist/types/util/3d-tilt-hover-effect.d.ts +1 -5
- package/package.json +6 -6
- package/dist/cjs/3d-tilt-hover-effect-f64da0a8.js.map +0 -1
- package/dist/esm/3d-tilt-hover-effect-a76fcd43.js.map +0 -1
- package/dist/lime-elements/p-05c10bed.entry.js.map +0 -1
- package/dist/lime-elements/p-1db8aa67.entry.js +0 -2
- package/dist/lime-elements/p-1db8aa67.entry.js.map +0 -1
- package/dist/lime-elements/p-23bc6de0.js.map +0 -1
- package/dist/lime-elements/p-68a8b724.entry.js +0 -2
- package/dist/lime-elements/p-68a8b724.entry.js.map +0 -1
- package/dist/lime-elements/p-ba4098bc.entry.js +0 -2
- package/dist/lime-elements/p-ba4098bc.entry.js.map +0 -1
- package/dist/lime-elements/p-f3a613a3.entry.js +0 -2
- package/dist/lime-elements/p-f3a613a3.entry.js.map +0 -1
|
@@ -5021,7 +5021,8 @@ class ReplaceAroundStep extends Step {
|
|
|
5021
5021
|
}
|
|
5022
5022
|
map(mapping) {
|
|
5023
5023
|
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
|
|
5024
|
-
let gapFrom =
|
|
5024
|
+
let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1);
|
|
5025
|
+
let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1);
|
|
5025
5026
|
if ((from.deletedAcross && to.deletedAcross) || gapFrom < from.pos || gapTo > to.pos)
|
|
5026
5027
|
return null;
|
|
5027
5028
|
return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure);
|
|
@@ -5133,7 +5134,7 @@ function removeMark(tr, from, to, mark) {
|
|
|
5133
5134
|
});
|
|
5134
5135
|
matched.forEach(m => tr.step(new RemoveMarkStep(m.from, m.to, m.style)));
|
|
5135
5136
|
}
|
|
5136
|
-
function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch) {
|
|
5137
|
+
function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch, clearNewlines = true) {
|
|
5137
5138
|
let node = tr.doc.nodeAt(pos);
|
|
5138
5139
|
let replSteps = [], cur = pos + 1;
|
|
5139
5140
|
for (let i = 0; i < node.childCount; i++) {
|
|
@@ -5147,7 +5148,7 @@ function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch)
|
|
|
5147
5148
|
for (let j = 0; j < child.marks.length; j++)
|
|
5148
5149
|
if (!parentType.allowsMarkType(child.marks[j].type))
|
|
5149
5150
|
tr.step(new RemoveMarkStep(cur, end, child.marks[j]));
|
|
5150
|
-
if (child.isText &&
|
|
5151
|
+
if (clearNewlines && child.isText && parentType.whitespace != "pre") {
|
|
5151
5152
|
let m, newline = /\r?\n|\r/g, slice;
|
|
5152
5153
|
while (m = newline.exec(child.text)) {
|
|
5153
5154
|
if (!slice)
|
|
@@ -5271,16 +5272,49 @@ function setBlockType$1(tr, from, to, type, attrs) {
|
|
|
5271
5272
|
throw new RangeError("Type given to setBlockType should be a textblock");
|
|
5272
5273
|
let mapFrom = tr.steps.length;
|
|
5273
5274
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
5274
|
-
|
|
5275
|
+
let attrsHere = typeof attrs == "function" ? attrs(node) : attrs;
|
|
5276
|
+
if (node.isTextblock && !node.hasMarkup(type, attrsHere) &&
|
|
5277
|
+
canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
|
|
5278
|
+
let convertNewlines = null;
|
|
5279
|
+
if (type.schema.linebreakReplacement) {
|
|
5280
|
+
let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement);
|
|
5281
|
+
if (pre && !supportLinebreak)
|
|
5282
|
+
convertNewlines = false;
|
|
5283
|
+
else if (!pre && supportLinebreak)
|
|
5284
|
+
convertNewlines = true;
|
|
5285
|
+
}
|
|
5275
5286
|
// Ensure all markup that isn't allowed in the new node type is cleared
|
|
5276
|
-
|
|
5287
|
+
if (convertNewlines === false)
|
|
5288
|
+
replaceLinebreaks(tr, node, pos, mapFrom);
|
|
5289
|
+
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null);
|
|
5277
5290
|
let mapping = tr.mapping.slice(mapFrom);
|
|
5278
5291
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
|
|
5279
|
-
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(
|
|
5292
|
+
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(attrsHere, null, node.marks)), 0, 0), 1, true));
|
|
5293
|
+
if (convertNewlines === true)
|
|
5294
|
+
replaceNewlines(tr, node, pos, mapFrom);
|
|
5280
5295
|
return false;
|
|
5281
5296
|
}
|
|
5282
5297
|
});
|
|
5283
5298
|
}
|
|
5299
|
+
function replaceNewlines(tr, node, pos, mapFrom) {
|
|
5300
|
+
node.forEach((child, offset) => {
|
|
5301
|
+
if (child.isText) {
|
|
5302
|
+
let m, newline = /\r?\n|\r/g;
|
|
5303
|
+
while (m = newline.exec(child.text)) {
|
|
5304
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index);
|
|
5305
|
+
tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement.create());
|
|
5306
|
+
}
|
|
5307
|
+
}
|
|
5308
|
+
});
|
|
5309
|
+
}
|
|
5310
|
+
function replaceLinebreaks(tr, node, pos, mapFrom) {
|
|
5311
|
+
node.forEach((child, offset) => {
|
|
5312
|
+
if (child.type == child.type.schema.linebreakReplacement) {
|
|
5313
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset);
|
|
5314
|
+
tr.replaceWith(start, start + 1, node.type.schema.text("\n"));
|
|
5315
|
+
}
|
|
5316
|
+
});
|
|
5317
|
+
}
|
|
5284
5318
|
function canChangeType(doc, pos, type) {
|
|
5285
5319
|
let $pos = doc.resolve(pos), index = $pos.index();
|
|
5286
5320
|
return $pos.parent.canReplaceWith(index, index + 1, type);
|
|
@@ -5346,8 +5380,24 @@ function canJoin(doc, pos) {
|
|
|
5346
5380
|
return joinable($pos.nodeBefore, $pos.nodeAfter) &&
|
|
5347
5381
|
$pos.parent.canReplace(index, index + 1);
|
|
5348
5382
|
}
|
|
5383
|
+
function canAppendWithSubstitutedLinebreaks(a, b) {
|
|
5384
|
+
if (!b.content.size)
|
|
5385
|
+
a.type.compatibleContent(b.type);
|
|
5386
|
+
let match = a.contentMatchAt(a.childCount);
|
|
5387
|
+
let { linebreakReplacement } = a.type.schema;
|
|
5388
|
+
for (let i = 0; i < b.childCount; i++) {
|
|
5389
|
+
let child = b.child(i);
|
|
5390
|
+
let type = child.type == linebreakReplacement ? a.type.schema.nodes.text : child.type;
|
|
5391
|
+
match = match.matchType(type);
|
|
5392
|
+
if (!match)
|
|
5393
|
+
return false;
|
|
5394
|
+
if (!a.type.allowsMarks(child.marks))
|
|
5395
|
+
return false;
|
|
5396
|
+
}
|
|
5397
|
+
return match.validEnd;
|
|
5398
|
+
}
|
|
5349
5399
|
function joinable(a, b) {
|
|
5350
|
-
return !!(a && b && !a.isLeaf && a
|
|
5400
|
+
return !!(a && b && !a.isLeaf && canAppendWithSubstitutedLinebreaks(a, b));
|
|
5351
5401
|
}
|
|
5352
5402
|
/**
|
|
5353
5403
|
Find an ancestor of the given position that can be joined to the
|
|
@@ -5380,8 +5430,31 @@ function joinPoint(doc, pos, dir = -1) {
|
|
|
5380
5430
|
}
|
|
5381
5431
|
}
|
|
5382
5432
|
function join(tr, pos, depth) {
|
|
5383
|
-
let
|
|
5384
|
-
tr.
|
|
5433
|
+
let convertNewlines = null;
|
|
5434
|
+
let { linebreakReplacement } = tr.doc.type.schema;
|
|
5435
|
+
let $before = tr.doc.resolve(pos - depth), beforeType = $before.node().type;
|
|
5436
|
+
if (linebreakReplacement && beforeType.inlineContent) {
|
|
5437
|
+
let pre = beforeType.whitespace == "pre";
|
|
5438
|
+
let supportLinebreak = !!beforeType.contentMatch.matchType(linebreakReplacement);
|
|
5439
|
+
if (pre && !supportLinebreak)
|
|
5440
|
+
convertNewlines = false;
|
|
5441
|
+
else if (!pre && supportLinebreak)
|
|
5442
|
+
convertNewlines = true;
|
|
5443
|
+
}
|
|
5444
|
+
let mapFrom = tr.steps.length;
|
|
5445
|
+
if (convertNewlines === false) {
|
|
5446
|
+
let $after = tr.doc.resolve(pos + depth);
|
|
5447
|
+
replaceLinebreaks(tr, $after.node(), $after.before(), mapFrom);
|
|
5448
|
+
}
|
|
5449
|
+
if (beforeType.inlineContent)
|
|
5450
|
+
clearIncompatible(tr, pos + depth - 1, beforeType, $before.node().contentMatchAt($before.index()), convertNewlines == null);
|
|
5451
|
+
let mapping = tr.mapping.slice(mapFrom), start = mapping.map(pos - depth);
|
|
5452
|
+
tr.step(new ReplaceStep(start, mapping.map(pos + depth, -1), Slice.empty, true));
|
|
5453
|
+
if (convertNewlines === true) {
|
|
5454
|
+
let $full = tr.doc.resolve(start);
|
|
5455
|
+
replaceNewlines(tr, $full.node(), $full.before(), tr.steps.length);
|
|
5456
|
+
}
|
|
5457
|
+
return tr;
|
|
5385
5458
|
}
|
|
5386
5459
|
/**
|
|
5387
5460
|
Try to find a point where a node of the given type can be inserted
|
|
@@ -5865,7 +5938,8 @@ function deleteRange(tr, from, to) {
|
|
|
5865
5938
|
return tr.delete($from.before(depth), $to.after(depth));
|
|
5866
5939
|
}
|
|
5867
5940
|
for (let d = 1; d <= $from.depth && d <= $to.depth; d++) {
|
|
5868
|
-
if (from - $from.start(d) == $from.depth - d && to > $from.end(d) && $to.end(d) - to != $to.depth - d
|
|
5941
|
+
if (from - $from.start(d) == $from.depth - d && to > $from.end(d) && $to.end(d) - to != $to.depth - d &&
|
|
5942
|
+
$from.start(d - 1) == $to.start(d - 1) && $from.node(d - 1).canReplace($from.index(d - 1), $to.index(d - 1)))
|
|
5869
5943
|
return tr.delete($from.before(d), to);
|
|
5870
5944
|
}
|
|
5871
5945
|
tr.delete(from, to);
|
|
@@ -7289,6 +7363,9 @@ const textRange = function (node, from, to) {
|
|
|
7289
7363
|
range.setStart(node, from || 0);
|
|
7290
7364
|
return range;
|
|
7291
7365
|
};
|
|
7366
|
+
const clearReusedRange = function () {
|
|
7367
|
+
reusedRange = null;
|
|
7368
|
+
};
|
|
7292
7369
|
// Scans forward and backward through DOM positions equivalent to the
|
|
7293
7370
|
// given one to see if the two are in the same place (i.e. after a
|
|
7294
7371
|
// text node vs at the end of that text node)
|
|
@@ -7323,6 +7400,44 @@ function scanFor(node, off, targetNode, targetOff, dir) {
|
|
|
7323
7400
|
function nodeSize(node) {
|
|
7324
7401
|
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
7325
7402
|
}
|
|
7403
|
+
function textNodeBefore$1(node, offset) {
|
|
7404
|
+
for (;;) {
|
|
7405
|
+
if (node.nodeType == 3 && offset)
|
|
7406
|
+
return node;
|
|
7407
|
+
if (node.nodeType == 1 && offset > 0) {
|
|
7408
|
+
if (node.contentEditable == "false")
|
|
7409
|
+
return null;
|
|
7410
|
+
node = node.childNodes[offset - 1];
|
|
7411
|
+
offset = nodeSize(node);
|
|
7412
|
+
}
|
|
7413
|
+
else if (node.parentNode && !hasBlockDesc(node)) {
|
|
7414
|
+
offset = domIndex(node);
|
|
7415
|
+
node = node.parentNode;
|
|
7416
|
+
}
|
|
7417
|
+
else {
|
|
7418
|
+
return null;
|
|
7419
|
+
}
|
|
7420
|
+
}
|
|
7421
|
+
}
|
|
7422
|
+
function textNodeAfter$1(node, offset) {
|
|
7423
|
+
for (;;) {
|
|
7424
|
+
if (node.nodeType == 3 && offset < node.nodeValue.length)
|
|
7425
|
+
return node;
|
|
7426
|
+
if (node.nodeType == 1 && offset < node.childNodes.length) {
|
|
7427
|
+
if (node.contentEditable == "false")
|
|
7428
|
+
return null;
|
|
7429
|
+
node = node.childNodes[offset];
|
|
7430
|
+
offset = 0;
|
|
7431
|
+
}
|
|
7432
|
+
else if (node.parentNode && !hasBlockDesc(node)) {
|
|
7433
|
+
offset = domIndex(node) + 1;
|
|
7434
|
+
node = node.parentNode;
|
|
7435
|
+
}
|
|
7436
|
+
else {
|
|
7437
|
+
return null;
|
|
7438
|
+
}
|
|
7439
|
+
}
|
|
7440
|
+
}
|
|
7326
7441
|
function isOnEdge(node, offset, parent) {
|
|
7327
7442
|
for (let atStart = offset == 0, atEnd = offset == nodeSize(node); atStart || atEnd;) {
|
|
7328
7443
|
if (node == parent)
|
|
@@ -7364,15 +7479,18 @@ function caretFromPoint(doc, x, y) {
|
|
|
7364
7479
|
if (doc.caretPositionFromPoint) {
|
|
7365
7480
|
try { // Firefox throws for this call in hard-to-predict circumstances (#994)
|
|
7366
7481
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
7482
|
+
// Clip the offset, because Chrome will return a text offset
|
|
7483
|
+
// into <input> nodes, which can't be treated as a regular DOM
|
|
7484
|
+
// offset
|
|
7367
7485
|
if (pos)
|
|
7368
|
-
return { node: pos.offsetNode, offset: pos.offset };
|
|
7486
|
+
return { node: pos.offsetNode, offset: Math.min(nodeSize(pos.offsetNode), pos.offset) };
|
|
7369
7487
|
}
|
|
7370
7488
|
catch (_) { }
|
|
7371
7489
|
}
|
|
7372
7490
|
if (doc.caretRangeFromPoint) {
|
|
7373
7491
|
let range = doc.caretRangeFromPoint(x, y);
|
|
7374
7492
|
if (range)
|
|
7375
|
-
return { node: range.startContainer, offset: range.startOffset };
|
|
7493
|
+
return { node: range.startContainer, offset: Math.min(nodeSize(range.startContainer), range.startOffset) };
|
|
7376
7494
|
}
|
|
7377
7495
|
}
|
|
7378
7496
|
|
|
@@ -7399,6 +7517,12 @@ const webkit = !!doc && "webkitFontSmoothing" in doc.documentElement.style;
|
|
|
7399
7517
|
const webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1] : 0;
|
|
7400
7518
|
|
|
7401
7519
|
function windowRect(doc) {
|
|
7520
|
+
let vp = doc.defaultView && doc.defaultView.visualViewport;
|
|
7521
|
+
if (vp)
|
|
7522
|
+
return {
|
|
7523
|
+
left: 0, right: vp.width,
|
|
7524
|
+
top: 0, bottom: vp.height
|
|
7525
|
+
};
|
|
7402
7526
|
return { left: 0, right: doc.documentElement.clientWidth,
|
|
7403
7527
|
top: 0, bottom: doc.documentElement.clientHeight };
|
|
7404
7528
|
}
|
|
@@ -7612,17 +7736,19 @@ function posFromCaret(view, node, offset, coords) {
|
|
|
7612
7736
|
for (let cur = node, sawBlock = false;;) {
|
|
7613
7737
|
if (cur == view.dom)
|
|
7614
7738
|
break;
|
|
7615
|
-
let desc = view.docView.nearestDesc(cur, true);
|
|
7739
|
+
let desc = view.docView.nearestDesc(cur, true), rect;
|
|
7616
7740
|
if (!desc)
|
|
7617
7741
|
return null;
|
|
7618
|
-
if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7742
|
+
if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) &&
|
|
7743
|
+
// Ignore elements with zero-size bounding rectangles
|
|
7744
|
+
((rect = desc.dom.getBoundingClientRect()).width || rect.height)) {
|
|
7745
|
+
if (desc.node.isBlock && desc.parent) {
|
|
7746
|
+
// Only apply the horizontal test to the innermost block. Vertical for any parent.
|
|
7747
|
+
if (!sawBlock && rect.left > coords.left || rect.top > coords.top)
|
|
7623
7748
|
outsideBlock = desc.posBefore;
|
|
7624
|
-
else if (rect.right < coords.left || rect.bottom < coords.top)
|
|
7749
|
+
else if (!sawBlock && rect.right < coords.left || rect.bottom < coords.top)
|
|
7625
7750
|
outsideBlock = desc.posAfter;
|
|
7751
|
+
sawBlock = true;
|
|
7626
7752
|
}
|
|
7627
7753
|
if (!desc.contentDOM && outsideBlock < 0 && !desc.node.isText) {
|
|
7628
7754
|
// If we are inside a leaf, return the side of the leaf closer to the coords
|
|
@@ -7877,6 +8003,8 @@ function endOfTextblockHorizontal(view, state, dir) {
|
|
|
7877
8003
|
return false;
|
|
7878
8004
|
let offset = $head.parentOffset, atStart = !offset, atEnd = offset == $head.parent.content.size;
|
|
7879
8005
|
let sel = view.domSelection();
|
|
8006
|
+
if (!sel)
|
|
8007
|
+
return $head.pos == $head.start() || $head.pos == $head.end();
|
|
7880
8008
|
// If the textblock is all LTR, or the browser doesn't support
|
|
7881
8009
|
// Selection.modify (Edge), fall back to a primitive approach
|
|
7882
8010
|
if (!maybeRTL.test($head.parent.textContent) || !sel.modify)
|
|
@@ -8209,18 +8337,19 @@ class ViewDesc {
|
|
|
8209
8337
|
// custom things with the selection. Note that this falls apart when
|
|
8210
8338
|
// a selection starts in such a node and ends in another, in which
|
|
8211
8339
|
// case we just use whatever domFromPos produces as a best effort.
|
|
8212
|
-
setSelection(anchor, head,
|
|
8340
|
+
setSelection(anchor, head, view, force = false) {
|
|
8213
8341
|
// If the selection falls entirely in a child, give it to that child
|
|
8214
8342
|
let from = Math.min(anchor, head), to = Math.max(anchor, head);
|
|
8215
8343
|
for (let i = 0, offset = 0; i < this.children.length; i++) {
|
|
8216
8344
|
let child = this.children[i], end = offset + child.size;
|
|
8217
8345
|
if (from > offset && to < end)
|
|
8218
|
-
return child.setSelection(anchor - offset - child.border, head - offset - child.border,
|
|
8346
|
+
return child.setSelection(anchor - offset - child.border, head - offset - child.border, view, force);
|
|
8219
8347
|
offset = end;
|
|
8220
8348
|
}
|
|
8221
8349
|
let anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1);
|
|
8222
8350
|
let headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1);
|
|
8223
|
-
let domSel = root.getSelection();
|
|
8351
|
+
let domSel = view.root.getSelection();
|
|
8352
|
+
let selRange = view.domSelectionRange();
|
|
8224
8353
|
let brKludge = false;
|
|
8225
8354
|
// On Firefox, using Selection.collapse to put the cursor after a
|
|
8226
8355
|
// BR node for some reason doesn't always work (#1073). On Safari,
|
|
@@ -8251,14 +8380,14 @@ class ViewDesc {
|
|
|
8251
8380
|
}
|
|
8252
8381
|
// Firefox can act strangely when the selection is in front of an
|
|
8253
8382
|
// uneditable node. See #1163 and https://bugzilla.mozilla.org/show_bug.cgi?id=1709536
|
|
8254
|
-
if (gecko &&
|
|
8255
|
-
let after =
|
|
8383
|
+
if (gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) {
|
|
8384
|
+
let after = selRange.focusNode.childNodes[selRange.focusOffset];
|
|
8256
8385
|
if (after && after.contentEditable == "false")
|
|
8257
8386
|
force = true;
|
|
8258
8387
|
}
|
|
8259
8388
|
if (!(force || brKludge && safari) &&
|
|
8260
|
-
isEquivalentPosition(anchorDOM.node, anchorDOM.offset,
|
|
8261
|
-
isEquivalentPosition(headDOM.node, headDOM.offset,
|
|
8389
|
+
isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) &&
|
|
8390
|
+
isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset))
|
|
8262
8391
|
return;
|
|
8263
8392
|
// Selection.extend can be used to create an 'inverted' selection
|
|
8264
8393
|
// (one where the focus is before the anchor), but not all
|
|
@@ -8334,6 +8463,7 @@ class ViewDesc {
|
|
|
8334
8463
|
}
|
|
8335
8464
|
get domAtom() { return false; }
|
|
8336
8465
|
get ignoreForCoords() { return false; }
|
|
8466
|
+
isText(text) { return false; }
|
|
8337
8467
|
}
|
|
8338
8468
|
// A widget desc represents a widget decoration, which is a DOM node
|
|
8339
8469
|
// drawn between the document nodes.
|
|
@@ -8404,16 +8534,17 @@ class CompositionViewDesc extends ViewDesc {
|
|
|
8404
8534
|
// some cases they will be split more often than would appear
|
|
8405
8535
|
// necessary.
|
|
8406
8536
|
class MarkViewDesc extends ViewDesc {
|
|
8407
|
-
constructor(parent, mark, dom, contentDOM) {
|
|
8537
|
+
constructor(parent, mark, dom, contentDOM, spec) {
|
|
8408
8538
|
super(parent, [], dom, contentDOM);
|
|
8409
8539
|
this.mark = mark;
|
|
8540
|
+
this.spec = spec;
|
|
8410
8541
|
}
|
|
8411
8542
|
static create(parent, mark, inline, view) {
|
|
8412
8543
|
let custom = view.nodeViews[mark.type.name];
|
|
8413
8544
|
let spec = custom && custom(mark, view, inline);
|
|
8414
8545
|
if (!spec || !spec.dom)
|
|
8415
|
-
spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline));
|
|
8416
|
-
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
|
|
8546
|
+
spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs);
|
|
8547
|
+
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom, spec);
|
|
8417
8548
|
}
|
|
8418
8549
|
parseRule() {
|
|
8419
8550
|
if ((this.dirty & NODE_DIRTY) || this.mark.type.spec.reparseInView)
|
|
@@ -8445,6 +8576,14 @@ class MarkViewDesc extends ViewDesc {
|
|
|
8445
8576
|
copy.children = nodes;
|
|
8446
8577
|
return copy;
|
|
8447
8578
|
}
|
|
8579
|
+
ignoreMutation(mutation) {
|
|
8580
|
+
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
|
|
8581
|
+
}
|
|
8582
|
+
destroy() {
|
|
8583
|
+
if (this.spec.destroy)
|
|
8584
|
+
this.spec.destroy();
|
|
8585
|
+
super.destroy();
|
|
8586
|
+
}
|
|
8448
8587
|
}
|
|
8449
8588
|
// Node view descs are the main, most common type of view desc, and
|
|
8450
8589
|
// correspond to an actual node in the document. Unlike mark descs,
|
|
@@ -8484,7 +8623,8 @@ class NodeViewDesc extends ViewDesc {
|
|
|
8484
8623
|
throw new RangeError("Text must be rendered as a DOM text node");
|
|
8485
8624
|
}
|
|
8486
8625
|
else if (!dom) {
|
|
8487
|
-
|
|
8626
|
+
let spec = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node), null, node.attrs);
|
|
8627
|
+
({ dom, contentDOM } = spec);
|
|
8488
8628
|
}
|
|
8489
8629
|
if (!contentDOM && !node.isText && dom.nodeName != "BR") { // Chrome gets confused by <br contenteditable=false>
|
|
8490
8630
|
if (!dom.hasAttribute("contenteditable"))
|
|
@@ -8596,8 +8736,7 @@ class NodeViewDesc extends ViewDesc {
|
|
|
8596
8736
|
let { from, to } = view.state.selection;
|
|
8597
8737
|
if (!(view.state.selection instanceof TextSelection) || from < pos || to > pos + this.node.content.size)
|
|
8598
8738
|
return null;
|
|
8599
|
-
let
|
|
8600
|
-
let textNode = nearbyTextNode(sel.focusNode, sel.focusOffset);
|
|
8739
|
+
let textNode = view.input.compositionNode;
|
|
8601
8740
|
if (!textNode || !this.dom.contains(textNode.parentNode))
|
|
8602
8741
|
return null;
|
|
8603
8742
|
if (this.node.inlineContent) {
|
|
@@ -8671,10 +8810,11 @@ class NodeViewDesc extends ViewDesc {
|
|
|
8671
8810
|
}
|
|
8672
8811
|
// Remove selected node marking from this node.
|
|
8673
8812
|
deselectNode() {
|
|
8674
|
-
if (this.nodeDOM.nodeType == 1)
|
|
8813
|
+
if (this.nodeDOM.nodeType == 1) {
|
|
8675
8814
|
this.nodeDOM.classList.remove("ProseMirror-selectednode");
|
|
8676
|
-
|
|
8677
|
-
|
|
8815
|
+
if (this.contentDOM || !this.node.type.spec.draggable)
|
|
8816
|
+
this.dom.removeAttribute("draggable");
|
|
8817
|
+
}
|
|
8678
8818
|
}
|
|
8679
8819
|
get domAtom() { return this.node.isAtom; }
|
|
8680
8820
|
}
|
|
@@ -8739,6 +8879,7 @@ class TextViewDesc extends NodeViewDesc {
|
|
|
8739
8879
|
this.dirty = NODE_DIRTY;
|
|
8740
8880
|
}
|
|
8741
8881
|
get domAtom() { return false; }
|
|
8882
|
+
isText(text) { return this.node.text == text; }
|
|
8742
8883
|
}
|
|
8743
8884
|
// A dummy desc used to tag trailing BR or IMG nodes created to work
|
|
8744
8885
|
// around contentEditable terribleness.
|
|
@@ -8762,7 +8903,7 @@ class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
8762
8903
|
update(node, outerDeco, innerDeco, view) {
|
|
8763
8904
|
if (this.dirty == NODE_DIRTY)
|
|
8764
8905
|
return false;
|
|
8765
|
-
if (this.spec.update) {
|
|
8906
|
+
if (this.spec.update && (this.node.type == node.type || this.spec.multiType)) {
|
|
8766
8907
|
let result = this.spec.update(node, outerDeco, innerDeco);
|
|
8767
8908
|
if (result)
|
|
8768
8909
|
this.updateInner(node, outerDeco, innerDeco, view);
|
|
@@ -8781,9 +8922,9 @@ class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
8781
8922
|
deselectNode() {
|
|
8782
8923
|
this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode();
|
|
8783
8924
|
}
|
|
8784
|
-
setSelection(anchor, head,
|
|
8785
|
-
this.spec.setSelection ? this.spec.setSelection(anchor, head, root)
|
|
8786
|
-
: super.setSelection(anchor, head,
|
|
8925
|
+
setSelection(anchor, head, view, force) {
|
|
8926
|
+
this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root)
|
|
8927
|
+
: super.setSelection(anchor, head, view, force);
|
|
8787
8928
|
}
|
|
8788
8929
|
destroy() {
|
|
8789
8930
|
if (this.spec.destroy)
|
|
@@ -9080,6 +9221,7 @@ class ViewTreeUpdater {
|
|
|
9080
9221
|
return true;
|
|
9081
9222
|
}
|
|
9082
9223
|
else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
|
|
9224
|
+
this.destroyBetween(this.index, i);
|
|
9083
9225
|
this.top.children[this.index] = updated;
|
|
9084
9226
|
if (updated.contentDOM) {
|
|
9085
9227
|
updated.dirty = CONTENT_DIRTY;
|
|
@@ -9099,7 +9241,8 @@ class ViewTreeUpdater {
|
|
|
9099
9241
|
// identical content, move over its children.
|
|
9100
9242
|
recreateWrapper(next, node, outerDeco, innerDeco, view, pos) {
|
|
9101
9243
|
if (next.dirty || node.isAtom || !next.children.length ||
|
|
9102
|
-
!next.node.content.eq(node.content)
|
|
9244
|
+
!next.node.content.eq(node.content) ||
|
|
9245
|
+
!sameOuterDeco(outerDeco, next.outerDeco) || !innerDeco.eq(next.innerDeco))
|
|
9103
9246
|
return null;
|
|
9104
9247
|
let wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
|
|
9105
9248
|
if (wrapper.contentDOM) {
|
|
@@ -9308,25 +9451,6 @@ function iosHacks(dom) {
|
|
|
9308
9451
|
dom.style.cssText = oldCSS;
|
|
9309
9452
|
}
|
|
9310
9453
|
}
|
|
9311
|
-
function nearbyTextNode(node, offset) {
|
|
9312
|
-
for (;;) {
|
|
9313
|
-
if (node.nodeType == 3)
|
|
9314
|
-
return node;
|
|
9315
|
-
if (node.nodeType == 1 && offset > 0) {
|
|
9316
|
-
if (node.childNodes.length > offset && node.childNodes[offset].nodeType == 3)
|
|
9317
|
-
return node.childNodes[offset];
|
|
9318
|
-
node = node.childNodes[offset - 1];
|
|
9319
|
-
offset = nodeSize(node);
|
|
9320
|
-
}
|
|
9321
|
-
else if (node.nodeType == 1 && offset < node.childNodes.length) {
|
|
9322
|
-
node = node.childNodes[offset];
|
|
9323
|
-
offset = 0;
|
|
9324
|
-
}
|
|
9325
|
-
else {
|
|
9326
|
-
return null;
|
|
9327
|
-
}
|
|
9328
|
-
}
|
|
9329
|
-
}
|
|
9330
9454
|
// Find a piece of text in an inline fragment, overlapping from-to
|
|
9331
9455
|
function findTextInFragment(frag, text, from, to) {
|
|
9332
9456
|
for (let i = 0, pos = 0; i < frag.childCount && pos <= to;) {
|
|
@@ -9389,9 +9513,9 @@ function selectionFromDOM(view, origin = null) {
|
|
|
9389
9513
|
let head = view.docView.posFromDOM(domSel.focusNode, domSel.focusOffset, 1);
|
|
9390
9514
|
if (head < 0)
|
|
9391
9515
|
return null;
|
|
9392
|
-
let $head = doc.resolve(head),
|
|
9516
|
+
let $head = doc.resolve(head), anchor, selection;
|
|
9393
9517
|
if (selectionCollapsed(domSel)) {
|
|
9394
|
-
|
|
9518
|
+
anchor = head;
|
|
9395
9519
|
while (nearestDesc && !nearestDesc.node)
|
|
9396
9520
|
nearestDesc = nearestDesc.parent;
|
|
9397
9521
|
let nearestDescNode = nearestDesc.node;
|
|
@@ -9402,11 +9526,25 @@ function selectionFromDOM(view, origin = null) {
|
|
|
9402
9526
|
}
|
|
9403
9527
|
}
|
|
9404
9528
|
else {
|
|
9405
|
-
|
|
9529
|
+
if (domSel instanceof view.dom.ownerDocument.defaultView.Selection && domSel.rangeCount > 1) {
|
|
9530
|
+
let min = head, max = head;
|
|
9531
|
+
for (let i = 0; i < domSel.rangeCount; i++) {
|
|
9532
|
+
let range = domSel.getRangeAt(i);
|
|
9533
|
+
min = Math.min(min, view.docView.posFromDOM(range.startContainer, range.startOffset, 1));
|
|
9534
|
+
max = Math.max(max, view.docView.posFromDOM(range.endContainer, range.endOffset, -1));
|
|
9535
|
+
}
|
|
9536
|
+
if (min < 0)
|
|
9537
|
+
return null;
|
|
9538
|
+
[anchor, head] = max == view.state.selection.anchor ? [max, min] : [min, max];
|
|
9539
|
+
$head = doc.resolve(head);
|
|
9540
|
+
}
|
|
9541
|
+
else {
|
|
9542
|
+
anchor = view.docView.posFromDOM(domSel.anchorNode, domSel.anchorOffset, 1);
|
|
9543
|
+
}
|
|
9406
9544
|
if (anchor < 0)
|
|
9407
9545
|
return null;
|
|
9408
|
-
$anchor = doc.resolve(anchor);
|
|
9409
9546
|
}
|
|
9547
|
+
let $anchor = doc.resolve(anchor);
|
|
9410
9548
|
if (!selection) {
|
|
9411
9549
|
let bias = origin == "pointer" || (view.state.selection.head < $head.pos && !inWidget) ? 1 : -1;
|
|
9412
9550
|
selection = selectionBetween(view, $anchor, $head, bias);
|
|
@@ -9446,7 +9584,7 @@ function selectionToDOM(view, force = false) {
|
|
|
9446
9584
|
if (!sel.empty && !sel.$from.parent.inlineContent)
|
|
9447
9585
|
resetEditableTo = temporarilyEditableNear(view, sel.to);
|
|
9448
9586
|
}
|
|
9449
|
-
view.docView.setSelection(anchor, head, view
|
|
9587
|
+
view.docView.setSelection(anchor, head, view, force);
|
|
9450
9588
|
if (brokenSelectBetweenUneditable) {
|
|
9451
9589
|
if (resetEditableFrom)
|
|
9452
9590
|
resetEditable(resetEditableFrom);
|
|
@@ -9515,12 +9653,14 @@ function removeClassOnSelectionChange(view) {
|
|
|
9515
9653
|
}
|
|
9516
9654
|
function selectCursorWrapper(view) {
|
|
9517
9655
|
let domSel = view.domSelection(), range = document.createRange();
|
|
9656
|
+
if (!domSel)
|
|
9657
|
+
return;
|
|
9518
9658
|
let node = view.cursorWrapper.dom, img = node.nodeName == "IMG";
|
|
9519
9659
|
if (img)
|
|
9520
|
-
range.
|
|
9660
|
+
range.setStart(node.parentNode, domIndex(node) + 1);
|
|
9521
9661
|
else
|
|
9522
|
-
range.
|
|
9523
|
-
range.collapse(
|
|
9662
|
+
range.setStart(node, 0);
|
|
9663
|
+
range.collapse(true);
|
|
9524
9664
|
domSel.removeAllRanges();
|
|
9525
9665
|
domSel.addRange(range);
|
|
9526
9666
|
// Kludge to kill 'control selection' in IE11 when selecting an
|
|
@@ -9808,6 +9948,8 @@ function setSelFocus(view, node, offset) {
|
|
|
9808
9948
|
}
|
|
9809
9949
|
}
|
|
9810
9950
|
let sel = view.domSelection();
|
|
9951
|
+
if (!sel)
|
|
9952
|
+
return;
|
|
9811
9953
|
if (selectionCollapsed(sel)) {
|
|
9812
9954
|
let range = document.createRange();
|
|
9813
9955
|
range.setEnd(node, offset);
|
|
@@ -9990,7 +10132,7 @@ function serializeForClipboard(view, slice) {
|
|
|
9990
10132
|
firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
|
|
9991
10133
|
let text = view.someProp("clipboardTextSerializer", f => f(slice, view)) ||
|
|
9992
10134
|
slice.content.textBetween(0, slice.content.size, "\n\n");
|
|
9993
|
-
return { dom: wrap, text };
|
|
10135
|
+
return { dom: wrap, text, slice };
|
|
9994
10136
|
}
|
|
9995
10137
|
// Read a slice of content from the clipboard (or drop data).
|
|
9996
10138
|
function parseFromClipboard(view, text, html, plainText, $context) {
|
|
@@ -10162,6 +10304,18 @@ let _detachedDoc = null;
|
|
|
10162
10304
|
function detachedDoc() {
|
|
10163
10305
|
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
|
|
10164
10306
|
}
|
|
10307
|
+
let _policy = null;
|
|
10308
|
+
function maybeWrapTrusted(html) {
|
|
10309
|
+
let trustedTypes = window.trustedTypes;
|
|
10310
|
+
if (!trustedTypes)
|
|
10311
|
+
return html;
|
|
10312
|
+
// With the require-trusted-types-for CSP, Chrome will block
|
|
10313
|
+
// innerHTML, even on a detached document. This wraps the string in
|
|
10314
|
+
// a way that makes the browser allow us to use its parser again.
|
|
10315
|
+
if (!_policy)
|
|
10316
|
+
_policy = trustedTypes.createPolicy("ProseMirrorClipboard", { createHTML: (s) => s });
|
|
10317
|
+
return _policy.createHTML(html);
|
|
10318
|
+
}
|
|
10165
10319
|
function readHTML(html) {
|
|
10166
10320
|
let metas = /^(\s*<meta [^>]*>)*/.exec(html);
|
|
10167
10321
|
if (metas)
|
|
@@ -10170,7 +10324,7 @@ function readHTML(html) {
|
|
|
10170
10324
|
let firstTag = /<([a-z][^>\s]+)/i.exec(html), wrap;
|
|
10171
10325
|
if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()])
|
|
10172
10326
|
html = wrap.map(n => "<" + n + ">").join("") + html + wrap.map(n => "</" + n + ">").reverse().join("");
|
|
10173
|
-
elt.innerHTML = html;
|
|
10327
|
+
elt.innerHTML = maybeWrapTrusted(html);
|
|
10174
10328
|
if (wrap)
|
|
10175
10329
|
for (let i = 0; i < wrap.length; i++)
|
|
10176
10330
|
elt = elt.querySelector(wrap[i]) || elt;
|
|
@@ -10229,8 +10383,9 @@ class InputState {
|
|
|
10229
10383
|
this.lastIOSEnterFallbackTimeout = -1;
|
|
10230
10384
|
this.lastFocus = 0;
|
|
10231
10385
|
this.lastTouch = 0;
|
|
10232
|
-
this.
|
|
10386
|
+
this.lastChromeDelete = 0;
|
|
10233
10387
|
this.composing = false;
|
|
10388
|
+
this.compositionNode = null;
|
|
10234
10389
|
this.composingTimeout = -1;
|
|
10235
10390
|
this.compositionNodes = [];
|
|
10236
10391
|
this.compositionEndedAt = -2e8;
|
|
@@ -10373,6 +10528,8 @@ function runHandlerOnContext(view, propName, pos, inside, event) {
|
|
|
10373
10528
|
function updateSelection(view, selection, origin) {
|
|
10374
10529
|
if (!view.focused)
|
|
10375
10530
|
view.focus();
|
|
10531
|
+
if (view.state.selection.eq(selection))
|
|
10532
|
+
return;
|
|
10376
10533
|
let tr = view.state.tr.setSelection(selection);
|
|
10377
10534
|
if (origin == "pointer")
|
|
10378
10535
|
tr.setMeta("pointer", true);
|
|
@@ -10506,7 +10663,7 @@ class MouseDown {
|
|
|
10506
10663
|
}
|
|
10507
10664
|
const target = flushed ? null : event.target;
|
|
10508
10665
|
const targetDesc = target ? view.docView.nearestDesc(target, true) : null;
|
|
10509
|
-
this.target = targetDesc ? targetDesc.dom : null;
|
|
10666
|
+
this.target = targetDesc && targetDesc.dom.nodeType == 1 ? targetDesc.dom : null;
|
|
10510
10667
|
let { selection } = view.state;
|
|
10511
10668
|
if (event.button == 0 &&
|
|
10512
10669
|
targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
|
|
@@ -10627,8 +10784,8 @@ const timeoutComposition = android ? 5000 : -1;
|
|
|
10627
10784
|
editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
10628
10785
|
if (!view.composing) {
|
|
10629
10786
|
view.domObserver.flush();
|
|
10630
|
-
let { state } = view, $pos = state.selection.$
|
|
10631
|
-
if (state.selection
|
|
10787
|
+
let { state } = view, $pos = state.selection.$to;
|
|
10788
|
+
if (state.selection instanceof TextSelection &&
|
|
10632
10789
|
(state.storedMarks ||
|
|
10633
10790
|
(!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(m => m.type.spec.inclusive === false)))) {
|
|
10634
10791
|
// Need to wrap the cursor in mark nodes different from the ones in the DOM context
|
|
@@ -10637,7 +10794,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
|
10637
10794
|
view.markCursor = null;
|
|
10638
10795
|
}
|
|
10639
10796
|
else {
|
|
10640
|
-
endComposition(view);
|
|
10797
|
+
endComposition(view, !state.selection.empty);
|
|
10641
10798
|
// In firefox, if the cursor is after but outside a marked node,
|
|
10642
10799
|
// the inserted text won't inherit the marks. So this moves it
|
|
10643
10800
|
// inside if necessary.
|
|
@@ -10648,7 +10805,9 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
|
10648
10805
|
if (!before)
|
|
10649
10806
|
break;
|
|
10650
10807
|
if (before.nodeType == 3) {
|
|
10651
|
-
view.domSelection()
|
|
10808
|
+
let sel = view.domSelection();
|
|
10809
|
+
if (sel)
|
|
10810
|
+
sel.collapse(before, before.nodeValue.length);
|
|
10652
10811
|
break;
|
|
10653
10812
|
}
|
|
10654
10813
|
else {
|
|
@@ -10667,6 +10826,7 @@ editHandlers.compositionend = (view, event) => {
|
|
|
10667
10826
|
view.input.composing = false;
|
|
10668
10827
|
view.input.compositionEndedAt = event.timeStamp;
|
|
10669
10828
|
view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
|
|
10829
|
+
view.input.compositionNode = null;
|
|
10670
10830
|
if (view.input.compositionPendingChanges)
|
|
10671
10831
|
Promise.resolve().then(() => view.domObserver.flush());
|
|
10672
10832
|
view.input.compositionID++;
|
|
@@ -10686,6 +10846,27 @@ function clearComposition(view) {
|
|
|
10686
10846
|
while (view.input.compositionNodes.length > 0)
|
|
10687
10847
|
view.input.compositionNodes.pop().markParentsDirty();
|
|
10688
10848
|
}
|
|
10849
|
+
function findCompositionNode(view) {
|
|
10850
|
+
let sel = view.domSelectionRange();
|
|
10851
|
+
if (!sel.focusNode)
|
|
10852
|
+
return null;
|
|
10853
|
+
let textBefore = textNodeBefore$1(sel.focusNode, sel.focusOffset);
|
|
10854
|
+
let textAfter = textNodeAfter$1(sel.focusNode, sel.focusOffset);
|
|
10855
|
+
if (textBefore && textAfter && textBefore != textAfter) {
|
|
10856
|
+
let descAfter = textAfter.pmViewDesc, lastChanged = view.domObserver.lastChangedTextNode;
|
|
10857
|
+
if (textBefore == lastChanged || textAfter == lastChanged)
|
|
10858
|
+
return lastChanged;
|
|
10859
|
+
if (!descAfter || !descAfter.isText(textAfter.nodeValue)) {
|
|
10860
|
+
return textAfter;
|
|
10861
|
+
}
|
|
10862
|
+
else if (view.input.compositionNode == textAfter) {
|
|
10863
|
+
let descBefore = textBefore.pmViewDesc;
|
|
10864
|
+
if (!(!descBefore || !descBefore.isText(textBefore.nodeValue)))
|
|
10865
|
+
return textAfter;
|
|
10866
|
+
}
|
|
10867
|
+
}
|
|
10868
|
+
return textBefore || textAfter;
|
|
10869
|
+
}
|
|
10689
10870
|
function timestampFromCustomEvent() {
|
|
10690
10871
|
let event = document.createEvent("Event");
|
|
10691
10872
|
event.initEvent("event", true, true);
|
|
@@ -10694,15 +10875,17 @@ function timestampFromCustomEvent() {
|
|
|
10694
10875
|
/**
|
|
10695
10876
|
@internal
|
|
10696
10877
|
*/
|
|
10697
|
-
function endComposition(view,
|
|
10878
|
+
function endComposition(view, restarting = false) {
|
|
10698
10879
|
if (android && view.domObserver.flushingSoon >= 0)
|
|
10699
10880
|
return;
|
|
10700
10881
|
view.domObserver.forceFlush();
|
|
10701
10882
|
clearComposition(view);
|
|
10702
|
-
if (
|
|
10883
|
+
if (restarting || view.docView && view.docView.dirty) {
|
|
10703
10884
|
let sel = selectionFromDOM(view);
|
|
10704
10885
|
if (sel && !sel.eq(view.state.selection))
|
|
10705
10886
|
view.dispatch(view.state.tr.setSelection(sel));
|
|
10887
|
+
else if ((view.markCursor || restarting) && !view.state.selection.empty)
|
|
10888
|
+
view.dispatch(view.state.tr.deleteSelection());
|
|
10706
10889
|
else
|
|
10707
10890
|
view.updateState(view.state);
|
|
10708
10891
|
return true;
|
|
@@ -10841,8 +11024,11 @@ handlers.dragstart = (view, _event) => {
|
|
|
10841
11024
|
if (desc && desc.node.type.spec.draggable && desc != view.docView)
|
|
10842
11025
|
node = NodeSelection.create(view.state.doc, desc.posBefore);
|
|
10843
11026
|
}
|
|
10844
|
-
let
|
|
10845
|
-
|
|
11027
|
+
let draggedSlice = (node || view.state.selection).content();
|
|
11028
|
+
let { dom, text, slice } = serializeForClipboard(view, draggedSlice);
|
|
11029
|
+
// Pre-120 Chrome versions clear files when calling `clearData` (#1472)
|
|
11030
|
+
if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
|
|
11031
|
+
event.dataTransfer.clearData();
|
|
10846
11032
|
event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
|
|
10847
11033
|
// See https://github.com/ProseMirror/prosemirror/issues/1156
|
|
10848
11034
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
@@ -11356,6 +11542,7 @@ class DecorationSet {
|
|
|
11356
11542
|
}
|
|
11357
11543
|
return result;
|
|
11358
11544
|
}
|
|
11545
|
+
forEachSet(f) { f(this); }
|
|
11359
11546
|
}
|
|
11360
11547
|
/**
|
|
11361
11548
|
The empty set of decorations.
|
|
@@ -11431,6 +11618,10 @@ class DecorationGroup {
|
|
|
11431
11618
|
members.reduce((r, m) => r.concat(m instanceof DecorationSet ? m : m.members), []));
|
|
11432
11619
|
}
|
|
11433
11620
|
}
|
|
11621
|
+
forEachSet(f) {
|
|
11622
|
+
for (let i = 0; i < this.members.length; i++)
|
|
11623
|
+
this.members[i].forEachSet(f);
|
|
11624
|
+
}
|
|
11434
11625
|
}
|
|
11435
11626
|
function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) {
|
|
11436
11627
|
let children = oldChildren.slice();
|
|
@@ -11685,6 +11876,7 @@ class DOMObserver {
|
|
|
11685
11876
|
this.currentSelection = new SelectionState;
|
|
11686
11877
|
this.onCharData = null;
|
|
11687
11878
|
this.suppressingSelectionUpdates = false;
|
|
11879
|
+
this.lastChangedTextNode = null;
|
|
11688
11880
|
this.observer = window.MutationObserver &&
|
|
11689
11881
|
new window.MutationObserver(mutations => {
|
|
11690
11882
|
for (let i = 0; i < mutations.length; i++)
|
|
@@ -11817,15 +12009,23 @@ class DOMObserver {
|
|
|
11817
12009
|
}
|
|
11818
12010
|
}
|
|
11819
12011
|
}
|
|
11820
|
-
if (gecko && added.length
|
|
12012
|
+
if (gecko && added.length) {
|
|
11821
12013
|
let brs = added.filter(n => n.nodeName == "BR");
|
|
11822
12014
|
if (brs.length == 2) {
|
|
11823
|
-
let a
|
|
12015
|
+
let [a, b] = brs;
|
|
11824
12016
|
if (a.parentNode && a.parentNode.parentNode == b.parentNode)
|
|
11825
12017
|
b.remove();
|
|
11826
12018
|
else
|
|
11827
12019
|
a.remove();
|
|
11828
12020
|
}
|
|
12021
|
+
else {
|
|
12022
|
+
let { focusNode } = this.currentSelection;
|
|
12023
|
+
for (let br of brs) {
|
|
12024
|
+
let parent = br.parentNode;
|
|
12025
|
+
if (parent && parent.nodeName == "LI" && (!focusNode || blockParent(view, focusNode) != parent))
|
|
12026
|
+
br.remove();
|
|
12027
|
+
}
|
|
12028
|
+
}
|
|
11829
12029
|
}
|
|
11830
12030
|
let readSel = null;
|
|
11831
12031
|
// If it looks like the browser has reset the selection to the
|
|
@@ -11866,8 +12066,12 @@ class DOMObserver {
|
|
|
11866
12066
|
if (!desc || desc.ignoreMutation(mut))
|
|
11867
12067
|
return null;
|
|
11868
12068
|
if (mut.type == "childList") {
|
|
11869
|
-
for (let i = 0; i < mut.addedNodes.length; i++)
|
|
11870
|
-
|
|
12069
|
+
for (let i = 0; i < mut.addedNodes.length; i++) {
|
|
12070
|
+
let node = mut.addedNodes[i];
|
|
12071
|
+
added.push(node);
|
|
12072
|
+
if (node.nodeType == 3)
|
|
12073
|
+
this.lastChangedTextNode = node;
|
|
12074
|
+
}
|
|
11871
12075
|
if (desc.contentDOM && desc.contentDOM != desc.dom && !desc.contentDOM.contains(mut.target))
|
|
11872
12076
|
return { from: desc.posBefore, to: desc.posAfter };
|
|
11873
12077
|
let prev = mut.previousSibling, next = mut.nextSibling;
|
|
@@ -11894,6 +12098,7 @@ class DOMObserver {
|
|
|
11894
12098
|
return { from: desc.posAtStart - desc.border, to: desc.posAtEnd + desc.border };
|
|
11895
12099
|
}
|
|
11896
12100
|
else { // "characterData"
|
|
12101
|
+
this.lastChangedTextNode = mut.target;
|
|
11897
12102
|
return {
|
|
11898
12103
|
from: desc.posAtStart,
|
|
11899
12104
|
to: desc.posAtEnd,
|
|
@@ -11920,9 +12125,25 @@ function checkCSS(view) {
|
|
|
11920
12125
|
cssCheckWarned = true;
|
|
11921
12126
|
}
|
|
11922
12127
|
}
|
|
12128
|
+
function rangeToSelectionRange(view, range) {
|
|
12129
|
+
let anchorNode = range.startContainer, anchorOffset = range.startOffset;
|
|
12130
|
+
let focusNode = range.endContainer, focusOffset = range.endOffset;
|
|
12131
|
+
let currentAnchor = view.domAtPos(view.state.selection.anchor);
|
|
12132
|
+
// Since such a range doesn't distinguish between anchor and head,
|
|
12133
|
+
// use a heuristic that flips it around if its end matches the
|
|
12134
|
+
// current anchor.
|
|
12135
|
+
if (isEquivalentPosition(currentAnchor.node, currentAnchor.offset, focusNode, focusOffset))
|
|
12136
|
+
[anchorNode, anchorOffset, focusNode, focusOffset] = [focusNode, focusOffset, anchorNode, anchorOffset];
|
|
12137
|
+
return { anchorNode, anchorOffset, focusNode, focusOffset };
|
|
12138
|
+
}
|
|
11923
12139
|
// Used to work around a Safari Selection/shadow DOM bug
|
|
11924
12140
|
// Based on https://github.com/codemirror/dev/issues/414 fix
|
|
11925
|
-
function safariShadowSelectionRange(view) {
|
|
12141
|
+
function safariShadowSelectionRange(view, selection) {
|
|
12142
|
+
if (selection.getComposedRanges) {
|
|
12143
|
+
let range = selection.getComposedRanges(view.root)[0];
|
|
12144
|
+
if (range)
|
|
12145
|
+
return rangeToSelectionRange(view, range);
|
|
12146
|
+
}
|
|
11926
12147
|
let found;
|
|
11927
12148
|
function read(event) {
|
|
11928
12149
|
event.preventDefault();
|
|
@@ -11937,15 +12158,15 @@ function safariShadowSelectionRange(view) {
|
|
|
11937
12158
|
view.dom.addEventListener("beforeinput", read, true);
|
|
11938
12159
|
document.execCommand("indent");
|
|
11939
12160
|
view.dom.removeEventListener("beforeinput", read, true);
|
|
11940
|
-
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
return
|
|
12161
|
+
return found ? rangeToSelectionRange(view, found) : null;
|
|
12162
|
+
}
|
|
12163
|
+
function blockParent(view, node) {
|
|
12164
|
+
for (let p = node.parentNode; p && p != view.dom; p = p.parentNode) {
|
|
12165
|
+
let desc = view.docView.nearestDesc(p, true);
|
|
12166
|
+
if (desc && desc.node.isBlock)
|
|
12167
|
+
return p;
|
|
12168
|
+
}
|
|
12169
|
+
return null;
|
|
11949
12170
|
}
|
|
11950
12171
|
|
|
11951
12172
|
// Note that all referencing and parsing is done with the
|
|
@@ -12063,6 +12284,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12063
12284
|
}
|
|
12064
12285
|
view.input.lastKeyCode = null;
|
|
12065
12286
|
let change = findDiff(compare.content, parse.doc.content, parse.from, preferredPos, preferredSide);
|
|
12287
|
+
if (change)
|
|
12288
|
+
view.input.domChangeCount++;
|
|
12066
12289
|
if ((ios && view.input.lastIOSEnter > Date.now() - 225 || android) &&
|
|
12067
12290
|
addedNodes.some(n => n.nodeType == 1 && !isInline.test(n.nodeName)) &&
|
|
12068
12291
|
(!change || change.endA >= change.endB) &&
|
|
@@ -12088,14 +12311,6 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12088
12311
|
return;
|
|
12089
12312
|
}
|
|
12090
12313
|
}
|
|
12091
|
-
// Chrome sometimes leaves the cursor before the inserted text when
|
|
12092
|
-
// composing after a cursor wrapper. This moves it forward.
|
|
12093
|
-
if (chrome && view.cursorWrapper && parse.sel && parse.sel.anchor == view.cursorWrapper.deco.from &&
|
|
12094
|
-
parse.sel.head == parse.sel.anchor) {
|
|
12095
|
-
let size = change.endB - change.start;
|
|
12096
|
-
parse.sel = { anchor: parse.sel.anchor + size, head: parse.sel.anchor + size };
|
|
12097
|
-
}
|
|
12098
|
-
view.input.domChangeCount++;
|
|
12099
12314
|
// Handle the case where overwriting a selection by typing matches
|
|
12100
12315
|
// the start or end of the selected content, creating a change
|
|
12101
12316
|
// that's smaller than what was actually overwritten.
|
|
@@ -12140,17 +12355,17 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12140
12355
|
}
|
|
12141
12356
|
// Same for backspace
|
|
12142
12357
|
if (view.state.selection.anchor > change.start &&
|
|
12143
|
-
|
|
12358
|
+
looksLikeBackspace(doc, change.start, change.endA, $from, $to) &&
|
|
12144
12359
|
view.someProp("handleKeyDown", f => f(view, keyEvent(8, "Backspace")))) {
|
|
12145
12360
|
if (android && chrome)
|
|
12146
12361
|
view.domObserver.suppressSelectionUpdates(); // #820
|
|
12147
12362
|
return;
|
|
12148
12363
|
}
|
|
12149
|
-
// Chrome
|
|
12364
|
+
// Chrome will occasionally, during composition, delete the
|
|
12150
12365
|
// entire composition and then immediately insert it again. This is
|
|
12151
12366
|
// used to detect that situation.
|
|
12152
|
-
if (chrome &&
|
|
12153
|
-
view.input.
|
|
12367
|
+
if (chrome && change.endB == change.start)
|
|
12368
|
+
view.input.lastChromeDelete = Date.now();
|
|
12154
12369
|
// This tries to detect Android virtual keyboard
|
|
12155
12370
|
// enter-and-pick-suggestion action. That sometimes (see issue
|
|
12156
12371
|
// #1059) first fires a DOM mutation, before moving the selection to
|
|
@@ -12201,13 +12416,13 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12201
12416
|
tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from));
|
|
12202
12417
|
if (parse.sel) {
|
|
12203
12418
|
let sel = resolveSelection(view, tr.doc, parse.sel);
|
|
12204
|
-
// Chrome
|
|
12419
|
+
// Chrome will sometimes, during composition, report the
|
|
12205
12420
|
// selection in the wrong place. If it looks like that is
|
|
12206
12421
|
// happening, don't update the selection.
|
|
12207
12422
|
// Edge just doesn't move the cursor forward when you start typing
|
|
12208
12423
|
// in an empty block or between br nodes.
|
|
12209
|
-
if (sel && !(chrome &&
|
|
12210
|
-
(change.start != change.endB || view.input.
|
|
12424
|
+
if (sel && !(chrome && view.composing && sel.empty &&
|
|
12425
|
+
(change.start != change.endB || view.input.lastChromeDelete < Date.now() - 100) &&
|
|
12211
12426
|
(sel.head == chFrom || sel.head == tr.mapping.map(chTo) - 1) ||
|
|
12212
12427
|
ie$1 && sel.empty && sel.head == chFrom))
|
|
12213
12428
|
tr.setSelection(sel);
|
|
@@ -12252,14 +12467,18 @@ function isMarkChange(cur, prev) {
|
|
|
12252
12467
|
if (Fragment.from(updated).eq(cur))
|
|
12253
12468
|
return { mark, type };
|
|
12254
12469
|
}
|
|
12255
|
-
function
|
|
12256
|
-
if (
|
|
12257
|
-
|
|
12258
|
-
end - start <= $newEnd.pos - $newStart.pos ||
|
|
12470
|
+
function looksLikeBackspace(old, start, end, $newStart, $newEnd) {
|
|
12471
|
+
if ( // The content must have shrunk
|
|
12472
|
+
end - start <= $newEnd.pos - $newStart.pos ||
|
|
12259
12473
|
// newEnd must point directly at or after the end of the block that newStart points into
|
|
12260
12474
|
skipClosingAndOpening($newStart, true, false) < $newEnd.pos)
|
|
12261
12475
|
return false;
|
|
12262
12476
|
let $start = old.resolve(start);
|
|
12477
|
+
// Handle the case where, rather than joining blocks, the change just removed an entire block
|
|
12478
|
+
if (!$newStart.parent.isTextblock) {
|
|
12479
|
+
let after = $start.nodeAfter;
|
|
12480
|
+
return after != null && end == start + after.nodeSize;
|
|
12481
|
+
}
|
|
12263
12482
|
// Start must be at the end of a block
|
|
12264
12483
|
if ($start.parentOffset < $start.parent.content.size || !$start.parent.isTextblock)
|
|
12265
12484
|
return false;
|
|
@@ -12497,8 +12716,10 @@ class EditorView {
|
|
|
12497
12716
|
// tracks that and forces a selection reset when our update
|
|
12498
12717
|
// did write to the node.
|
|
12499
12718
|
let chromeKludge = chrome ? (this.trackWrites = this.domSelectionRange().focusNode) : null;
|
|
12719
|
+
if (this.composing)
|
|
12720
|
+
this.input.compositionNode = findCompositionNode(this);
|
|
12500
12721
|
if (redraw || !this.docView.update(state.doc, outerDeco, innerDeco, this)) {
|
|
12501
|
-
this.docView.updateOuterDeco(
|
|
12722
|
+
this.docView.updateOuterDeco(outerDeco);
|
|
12502
12723
|
this.docView.destroy();
|
|
12503
12724
|
this.docView = docViewDesc(state.doc, outerDeco, innerDeco, this.dom, this);
|
|
12504
12725
|
}
|
|
@@ -12775,6 +12996,7 @@ class EditorView {
|
|
|
12775
12996
|
}
|
|
12776
12997
|
this.docView.destroy();
|
|
12777
12998
|
this.docView = null;
|
|
12999
|
+
clearReusedRange();
|
|
12778
13000
|
}
|
|
12779
13001
|
/**
|
|
12780
13002
|
This is true when the view has been
|
|
@@ -12810,8 +13032,11 @@ class EditorView {
|
|
|
12810
13032
|
@internal
|
|
12811
13033
|
*/
|
|
12812
13034
|
domSelectionRange() {
|
|
12813
|
-
|
|
12814
|
-
|
|
13035
|
+
let sel = this.domSelection();
|
|
13036
|
+
if (!sel)
|
|
13037
|
+
return { focusNode: null, focusOffset: 0, anchorNode: null, anchorOffset: 0 };
|
|
13038
|
+
return safari && this.root.nodeType === 11 &&
|
|
13039
|
+
deepActiveElement(this.dom.ownerDocument) == this.dom && safariShadowSelectionRange(this, sel) || sel;
|
|
12815
13040
|
}
|
|
12816
13041
|
/**
|
|
12817
13042
|
@internal
|
|
@@ -12847,7 +13072,7 @@ function updateCursorWrapper(view) {
|
|
|
12847
13072
|
dom.className = "ProseMirror-separator";
|
|
12848
13073
|
dom.setAttribute("mark-placeholder", "true");
|
|
12849
13074
|
dom.setAttribute("alt", "");
|
|
12850
|
-
view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.
|
|
13075
|
+
view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.from, dom, { raw: true, marks: view.markCursor }) };
|
|
12851
13076
|
}
|
|
12852
13077
|
else {
|
|
12853
13078
|
view.cursorWrapper = null;
|