@limetech/lime-elements 37.78.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 +8 -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-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/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-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-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/shortcut/shortcut.d.ts +5 -1
- package/dist/types/components.d.ts +57 -0
- 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-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
|
@@ -5025,7 +5025,8 @@ class ReplaceAroundStep extends Step {
|
|
|
5025
5025
|
}
|
|
5026
5026
|
map(mapping) {
|
|
5027
5027
|
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
|
|
5028
|
-
let gapFrom =
|
|
5028
|
+
let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1);
|
|
5029
|
+
let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1);
|
|
5029
5030
|
if ((from.deletedAcross && to.deletedAcross) || gapFrom < from.pos || gapTo > to.pos)
|
|
5030
5031
|
return null;
|
|
5031
5032
|
return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure);
|
|
@@ -5137,7 +5138,7 @@ function removeMark(tr, from, to, mark) {
|
|
|
5137
5138
|
});
|
|
5138
5139
|
matched.forEach(m => tr.step(new RemoveMarkStep(m.from, m.to, m.style)));
|
|
5139
5140
|
}
|
|
5140
|
-
function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch) {
|
|
5141
|
+
function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch, clearNewlines = true) {
|
|
5141
5142
|
let node = tr.doc.nodeAt(pos);
|
|
5142
5143
|
let replSteps = [], cur = pos + 1;
|
|
5143
5144
|
for (let i = 0; i < node.childCount; i++) {
|
|
@@ -5151,7 +5152,7 @@ function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch)
|
|
|
5151
5152
|
for (let j = 0; j < child.marks.length; j++)
|
|
5152
5153
|
if (!parentType.allowsMarkType(child.marks[j].type))
|
|
5153
5154
|
tr.step(new RemoveMarkStep(cur, end, child.marks[j]));
|
|
5154
|
-
if (child.isText &&
|
|
5155
|
+
if (clearNewlines && child.isText && parentType.whitespace != "pre") {
|
|
5155
5156
|
let m, newline = /\r?\n|\r/g, slice;
|
|
5156
5157
|
while (m = newline.exec(child.text)) {
|
|
5157
5158
|
if (!slice)
|
|
@@ -5275,16 +5276,49 @@ function setBlockType$1(tr, from, to, type, attrs) {
|
|
|
5275
5276
|
throw new RangeError("Type given to setBlockType should be a textblock");
|
|
5276
5277
|
let mapFrom = tr.steps.length;
|
|
5277
5278
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
5278
|
-
|
|
5279
|
+
let attrsHere = typeof attrs == "function" ? attrs(node) : attrs;
|
|
5280
|
+
if (node.isTextblock && !node.hasMarkup(type, attrsHere) &&
|
|
5281
|
+
canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
|
|
5282
|
+
let convertNewlines = null;
|
|
5283
|
+
if (type.schema.linebreakReplacement) {
|
|
5284
|
+
let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement);
|
|
5285
|
+
if (pre && !supportLinebreak)
|
|
5286
|
+
convertNewlines = false;
|
|
5287
|
+
else if (!pre && supportLinebreak)
|
|
5288
|
+
convertNewlines = true;
|
|
5289
|
+
}
|
|
5279
5290
|
// Ensure all markup that isn't allowed in the new node type is cleared
|
|
5280
|
-
|
|
5291
|
+
if (convertNewlines === false)
|
|
5292
|
+
replaceLinebreaks(tr, node, pos, mapFrom);
|
|
5293
|
+
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null);
|
|
5281
5294
|
let mapping = tr.mapping.slice(mapFrom);
|
|
5282
5295
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
|
|
5283
|
-
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(
|
|
5296
|
+
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(attrsHere, null, node.marks)), 0, 0), 1, true));
|
|
5297
|
+
if (convertNewlines === true)
|
|
5298
|
+
replaceNewlines(tr, node, pos, mapFrom);
|
|
5284
5299
|
return false;
|
|
5285
5300
|
}
|
|
5286
5301
|
});
|
|
5287
5302
|
}
|
|
5303
|
+
function replaceNewlines(tr, node, pos, mapFrom) {
|
|
5304
|
+
node.forEach((child, offset) => {
|
|
5305
|
+
if (child.isText) {
|
|
5306
|
+
let m, newline = /\r?\n|\r/g;
|
|
5307
|
+
while (m = newline.exec(child.text)) {
|
|
5308
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index);
|
|
5309
|
+
tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement.create());
|
|
5310
|
+
}
|
|
5311
|
+
}
|
|
5312
|
+
});
|
|
5313
|
+
}
|
|
5314
|
+
function replaceLinebreaks(tr, node, pos, mapFrom) {
|
|
5315
|
+
node.forEach((child, offset) => {
|
|
5316
|
+
if (child.type == child.type.schema.linebreakReplacement) {
|
|
5317
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset);
|
|
5318
|
+
tr.replaceWith(start, start + 1, node.type.schema.text("\n"));
|
|
5319
|
+
}
|
|
5320
|
+
});
|
|
5321
|
+
}
|
|
5288
5322
|
function canChangeType(doc, pos, type) {
|
|
5289
5323
|
let $pos = doc.resolve(pos), index = $pos.index();
|
|
5290
5324
|
return $pos.parent.canReplaceWith(index, index + 1, type);
|
|
@@ -5350,8 +5384,24 @@ function canJoin(doc, pos) {
|
|
|
5350
5384
|
return joinable($pos.nodeBefore, $pos.nodeAfter) &&
|
|
5351
5385
|
$pos.parent.canReplace(index, index + 1);
|
|
5352
5386
|
}
|
|
5387
|
+
function canAppendWithSubstitutedLinebreaks(a, b) {
|
|
5388
|
+
if (!b.content.size)
|
|
5389
|
+
a.type.compatibleContent(b.type);
|
|
5390
|
+
let match = a.contentMatchAt(a.childCount);
|
|
5391
|
+
let { linebreakReplacement } = a.type.schema;
|
|
5392
|
+
for (let i = 0; i < b.childCount; i++) {
|
|
5393
|
+
let child = b.child(i);
|
|
5394
|
+
let type = child.type == linebreakReplacement ? a.type.schema.nodes.text : child.type;
|
|
5395
|
+
match = match.matchType(type);
|
|
5396
|
+
if (!match)
|
|
5397
|
+
return false;
|
|
5398
|
+
if (!a.type.allowsMarks(child.marks))
|
|
5399
|
+
return false;
|
|
5400
|
+
}
|
|
5401
|
+
return match.validEnd;
|
|
5402
|
+
}
|
|
5353
5403
|
function joinable(a, b) {
|
|
5354
|
-
return !!(a && b && !a.isLeaf && a
|
|
5404
|
+
return !!(a && b && !a.isLeaf && canAppendWithSubstitutedLinebreaks(a, b));
|
|
5355
5405
|
}
|
|
5356
5406
|
/**
|
|
5357
5407
|
Find an ancestor of the given position that can be joined to the
|
|
@@ -5384,8 +5434,31 @@ function joinPoint(doc, pos, dir = -1) {
|
|
|
5384
5434
|
}
|
|
5385
5435
|
}
|
|
5386
5436
|
function join(tr, pos, depth) {
|
|
5387
|
-
let
|
|
5388
|
-
tr.
|
|
5437
|
+
let convertNewlines = null;
|
|
5438
|
+
let { linebreakReplacement } = tr.doc.type.schema;
|
|
5439
|
+
let $before = tr.doc.resolve(pos - depth), beforeType = $before.node().type;
|
|
5440
|
+
if (linebreakReplacement && beforeType.inlineContent) {
|
|
5441
|
+
let pre = beforeType.whitespace == "pre";
|
|
5442
|
+
let supportLinebreak = !!beforeType.contentMatch.matchType(linebreakReplacement);
|
|
5443
|
+
if (pre && !supportLinebreak)
|
|
5444
|
+
convertNewlines = false;
|
|
5445
|
+
else if (!pre && supportLinebreak)
|
|
5446
|
+
convertNewlines = true;
|
|
5447
|
+
}
|
|
5448
|
+
let mapFrom = tr.steps.length;
|
|
5449
|
+
if (convertNewlines === false) {
|
|
5450
|
+
let $after = tr.doc.resolve(pos + depth);
|
|
5451
|
+
replaceLinebreaks(tr, $after.node(), $after.before(), mapFrom);
|
|
5452
|
+
}
|
|
5453
|
+
if (beforeType.inlineContent)
|
|
5454
|
+
clearIncompatible(tr, pos + depth - 1, beforeType, $before.node().contentMatchAt($before.index()), convertNewlines == null);
|
|
5455
|
+
let mapping = tr.mapping.slice(mapFrom), start = mapping.map(pos - depth);
|
|
5456
|
+
tr.step(new ReplaceStep(start, mapping.map(pos + depth, -1), Slice.empty, true));
|
|
5457
|
+
if (convertNewlines === true) {
|
|
5458
|
+
let $full = tr.doc.resolve(start);
|
|
5459
|
+
replaceNewlines(tr, $full.node(), $full.before(), tr.steps.length);
|
|
5460
|
+
}
|
|
5461
|
+
return tr;
|
|
5389
5462
|
}
|
|
5390
5463
|
/**
|
|
5391
5464
|
Try to find a point where a node of the given type can be inserted
|
|
@@ -5869,7 +5942,8 @@ function deleteRange(tr, from, to) {
|
|
|
5869
5942
|
return tr.delete($from.before(depth), $to.after(depth));
|
|
5870
5943
|
}
|
|
5871
5944
|
for (let d = 1; d <= $from.depth && d <= $to.depth; d++) {
|
|
5872
|
-
if (from - $from.start(d) == $from.depth - d && to > $from.end(d) && $to.end(d) - to != $to.depth - d
|
|
5945
|
+
if (from - $from.start(d) == $from.depth - d && to > $from.end(d) && $to.end(d) - to != $to.depth - d &&
|
|
5946
|
+
$from.start(d - 1) == $to.start(d - 1) && $from.node(d - 1).canReplace($from.index(d - 1), $to.index(d - 1)))
|
|
5873
5947
|
return tr.delete($from.before(d), to);
|
|
5874
5948
|
}
|
|
5875
5949
|
tr.delete(from, to);
|
|
@@ -7293,6 +7367,9 @@ const textRange = function (node, from, to) {
|
|
|
7293
7367
|
range.setStart(node, from || 0);
|
|
7294
7368
|
return range;
|
|
7295
7369
|
};
|
|
7370
|
+
const clearReusedRange = function () {
|
|
7371
|
+
reusedRange = null;
|
|
7372
|
+
};
|
|
7296
7373
|
// Scans forward and backward through DOM positions equivalent to the
|
|
7297
7374
|
// given one to see if the two are in the same place (i.e. after a
|
|
7298
7375
|
// text node vs at the end of that text node)
|
|
@@ -7327,6 +7404,44 @@ function scanFor(node, off, targetNode, targetOff, dir) {
|
|
|
7327
7404
|
function nodeSize(node) {
|
|
7328
7405
|
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
7329
7406
|
}
|
|
7407
|
+
function textNodeBefore$1(node, offset) {
|
|
7408
|
+
for (;;) {
|
|
7409
|
+
if (node.nodeType == 3 && offset)
|
|
7410
|
+
return node;
|
|
7411
|
+
if (node.nodeType == 1 && offset > 0) {
|
|
7412
|
+
if (node.contentEditable == "false")
|
|
7413
|
+
return null;
|
|
7414
|
+
node = node.childNodes[offset - 1];
|
|
7415
|
+
offset = nodeSize(node);
|
|
7416
|
+
}
|
|
7417
|
+
else if (node.parentNode && !hasBlockDesc(node)) {
|
|
7418
|
+
offset = domIndex(node);
|
|
7419
|
+
node = node.parentNode;
|
|
7420
|
+
}
|
|
7421
|
+
else {
|
|
7422
|
+
return null;
|
|
7423
|
+
}
|
|
7424
|
+
}
|
|
7425
|
+
}
|
|
7426
|
+
function textNodeAfter$1(node, offset) {
|
|
7427
|
+
for (;;) {
|
|
7428
|
+
if (node.nodeType == 3 && offset < node.nodeValue.length)
|
|
7429
|
+
return node;
|
|
7430
|
+
if (node.nodeType == 1 && offset < node.childNodes.length) {
|
|
7431
|
+
if (node.contentEditable == "false")
|
|
7432
|
+
return null;
|
|
7433
|
+
node = node.childNodes[offset];
|
|
7434
|
+
offset = 0;
|
|
7435
|
+
}
|
|
7436
|
+
else if (node.parentNode && !hasBlockDesc(node)) {
|
|
7437
|
+
offset = domIndex(node) + 1;
|
|
7438
|
+
node = node.parentNode;
|
|
7439
|
+
}
|
|
7440
|
+
else {
|
|
7441
|
+
return null;
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
}
|
|
7330
7445
|
function isOnEdge(node, offset, parent) {
|
|
7331
7446
|
for (let atStart = offset == 0, atEnd = offset == nodeSize(node); atStart || atEnd;) {
|
|
7332
7447
|
if (node == parent)
|
|
@@ -7368,15 +7483,18 @@ function caretFromPoint(doc, x, y) {
|
|
|
7368
7483
|
if (doc.caretPositionFromPoint) {
|
|
7369
7484
|
try { // Firefox throws for this call in hard-to-predict circumstances (#994)
|
|
7370
7485
|
let pos = doc.caretPositionFromPoint(x, y);
|
|
7486
|
+
// Clip the offset, because Chrome will return a text offset
|
|
7487
|
+
// into <input> nodes, which can't be treated as a regular DOM
|
|
7488
|
+
// offset
|
|
7371
7489
|
if (pos)
|
|
7372
|
-
return { node: pos.offsetNode, offset: pos.offset };
|
|
7490
|
+
return { node: pos.offsetNode, offset: Math.min(nodeSize(pos.offsetNode), pos.offset) };
|
|
7373
7491
|
}
|
|
7374
7492
|
catch (_) { }
|
|
7375
7493
|
}
|
|
7376
7494
|
if (doc.caretRangeFromPoint) {
|
|
7377
7495
|
let range = doc.caretRangeFromPoint(x, y);
|
|
7378
7496
|
if (range)
|
|
7379
|
-
return { node: range.startContainer, offset: range.startOffset };
|
|
7497
|
+
return { node: range.startContainer, offset: Math.min(nodeSize(range.startContainer), range.startOffset) };
|
|
7380
7498
|
}
|
|
7381
7499
|
}
|
|
7382
7500
|
|
|
@@ -7403,6 +7521,12 @@ const webkit = !!doc && "webkitFontSmoothing" in doc.documentElement.style;
|
|
|
7403
7521
|
const webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1] : 0;
|
|
7404
7522
|
|
|
7405
7523
|
function windowRect(doc) {
|
|
7524
|
+
let vp = doc.defaultView && doc.defaultView.visualViewport;
|
|
7525
|
+
if (vp)
|
|
7526
|
+
return {
|
|
7527
|
+
left: 0, right: vp.width,
|
|
7528
|
+
top: 0, bottom: vp.height
|
|
7529
|
+
};
|
|
7406
7530
|
return { left: 0, right: doc.documentElement.clientWidth,
|
|
7407
7531
|
top: 0, bottom: doc.documentElement.clientHeight };
|
|
7408
7532
|
}
|
|
@@ -7616,17 +7740,19 @@ function posFromCaret(view, node, offset, coords) {
|
|
|
7616
7740
|
for (let cur = node, sawBlock = false;;) {
|
|
7617
7741
|
if (cur == view.dom)
|
|
7618
7742
|
break;
|
|
7619
|
-
let desc = view.docView.nearestDesc(cur, true);
|
|
7743
|
+
let desc = view.docView.nearestDesc(cur, true), rect;
|
|
7620
7744
|
if (!desc)
|
|
7621
7745
|
return null;
|
|
7622
|
-
if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7746
|
+
if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent || !desc.contentDOM) &&
|
|
7747
|
+
// Ignore elements with zero-size bounding rectangles
|
|
7748
|
+
((rect = desc.dom.getBoundingClientRect()).width || rect.height)) {
|
|
7749
|
+
if (desc.node.isBlock && desc.parent) {
|
|
7750
|
+
// Only apply the horizontal test to the innermost block. Vertical for any parent.
|
|
7751
|
+
if (!sawBlock && rect.left > coords.left || rect.top > coords.top)
|
|
7627
7752
|
outsideBlock = desc.posBefore;
|
|
7628
|
-
else if (rect.right < coords.left || rect.bottom < coords.top)
|
|
7753
|
+
else if (!sawBlock && rect.right < coords.left || rect.bottom < coords.top)
|
|
7629
7754
|
outsideBlock = desc.posAfter;
|
|
7755
|
+
sawBlock = true;
|
|
7630
7756
|
}
|
|
7631
7757
|
if (!desc.contentDOM && outsideBlock < 0 && !desc.node.isText) {
|
|
7632
7758
|
// If we are inside a leaf, return the side of the leaf closer to the coords
|
|
@@ -7881,6 +8007,8 @@ function endOfTextblockHorizontal(view, state, dir) {
|
|
|
7881
8007
|
return false;
|
|
7882
8008
|
let offset = $head.parentOffset, atStart = !offset, atEnd = offset == $head.parent.content.size;
|
|
7883
8009
|
let sel = view.domSelection();
|
|
8010
|
+
if (!sel)
|
|
8011
|
+
return $head.pos == $head.start() || $head.pos == $head.end();
|
|
7884
8012
|
// If the textblock is all LTR, or the browser doesn't support
|
|
7885
8013
|
// Selection.modify (Edge), fall back to a primitive approach
|
|
7886
8014
|
if (!maybeRTL.test($head.parent.textContent) || !sel.modify)
|
|
@@ -8213,18 +8341,19 @@ class ViewDesc {
|
|
|
8213
8341
|
// custom things with the selection. Note that this falls apart when
|
|
8214
8342
|
// a selection starts in such a node and ends in another, in which
|
|
8215
8343
|
// case we just use whatever domFromPos produces as a best effort.
|
|
8216
|
-
setSelection(anchor, head,
|
|
8344
|
+
setSelection(anchor, head, view, force = false) {
|
|
8217
8345
|
// If the selection falls entirely in a child, give it to that child
|
|
8218
8346
|
let from = Math.min(anchor, head), to = Math.max(anchor, head);
|
|
8219
8347
|
for (let i = 0, offset = 0; i < this.children.length; i++) {
|
|
8220
8348
|
let child = this.children[i], end = offset + child.size;
|
|
8221
8349
|
if (from > offset && to < end)
|
|
8222
|
-
return child.setSelection(anchor - offset - child.border, head - offset - child.border,
|
|
8350
|
+
return child.setSelection(anchor - offset - child.border, head - offset - child.border, view, force);
|
|
8223
8351
|
offset = end;
|
|
8224
8352
|
}
|
|
8225
8353
|
let anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1);
|
|
8226
8354
|
let headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1);
|
|
8227
|
-
let domSel = root.getSelection();
|
|
8355
|
+
let domSel = view.root.getSelection();
|
|
8356
|
+
let selRange = view.domSelectionRange();
|
|
8228
8357
|
let brKludge = false;
|
|
8229
8358
|
// On Firefox, using Selection.collapse to put the cursor after a
|
|
8230
8359
|
// BR node for some reason doesn't always work (#1073). On Safari,
|
|
@@ -8255,14 +8384,14 @@ class ViewDesc {
|
|
|
8255
8384
|
}
|
|
8256
8385
|
// Firefox can act strangely when the selection is in front of an
|
|
8257
8386
|
// uneditable node. See #1163 and https://bugzilla.mozilla.org/show_bug.cgi?id=1709536
|
|
8258
|
-
if (gecko &&
|
|
8259
|
-
let after =
|
|
8387
|
+
if (gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) {
|
|
8388
|
+
let after = selRange.focusNode.childNodes[selRange.focusOffset];
|
|
8260
8389
|
if (after && after.contentEditable == "false")
|
|
8261
8390
|
force = true;
|
|
8262
8391
|
}
|
|
8263
8392
|
if (!(force || brKludge && safari) &&
|
|
8264
|
-
isEquivalentPosition(anchorDOM.node, anchorDOM.offset,
|
|
8265
|
-
isEquivalentPosition(headDOM.node, headDOM.offset,
|
|
8393
|
+
isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) &&
|
|
8394
|
+
isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset))
|
|
8266
8395
|
return;
|
|
8267
8396
|
// Selection.extend can be used to create an 'inverted' selection
|
|
8268
8397
|
// (one where the focus is before the anchor), but not all
|
|
@@ -8338,6 +8467,7 @@ class ViewDesc {
|
|
|
8338
8467
|
}
|
|
8339
8468
|
get domAtom() { return false; }
|
|
8340
8469
|
get ignoreForCoords() { return false; }
|
|
8470
|
+
isText(text) { return false; }
|
|
8341
8471
|
}
|
|
8342
8472
|
// A widget desc represents a widget decoration, which is a DOM node
|
|
8343
8473
|
// drawn between the document nodes.
|
|
@@ -8408,16 +8538,17 @@ class CompositionViewDesc extends ViewDesc {
|
|
|
8408
8538
|
// some cases they will be split more often than would appear
|
|
8409
8539
|
// necessary.
|
|
8410
8540
|
class MarkViewDesc extends ViewDesc {
|
|
8411
|
-
constructor(parent, mark, dom, contentDOM) {
|
|
8541
|
+
constructor(parent, mark, dom, contentDOM, spec) {
|
|
8412
8542
|
super(parent, [], dom, contentDOM);
|
|
8413
8543
|
this.mark = mark;
|
|
8544
|
+
this.spec = spec;
|
|
8414
8545
|
}
|
|
8415
8546
|
static create(parent, mark, inline, view) {
|
|
8416
8547
|
let custom = view.nodeViews[mark.type.name];
|
|
8417
8548
|
let spec = custom && custom(mark, view, inline);
|
|
8418
8549
|
if (!spec || !spec.dom)
|
|
8419
|
-
spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline));
|
|
8420
|
-
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
|
|
8550
|
+
spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs);
|
|
8551
|
+
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom, spec);
|
|
8421
8552
|
}
|
|
8422
8553
|
parseRule() {
|
|
8423
8554
|
if ((this.dirty & NODE_DIRTY) || this.mark.type.spec.reparseInView)
|
|
@@ -8449,6 +8580,14 @@ class MarkViewDesc extends ViewDesc {
|
|
|
8449
8580
|
copy.children = nodes;
|
|
8450
8581
|
return copy;
|
|
8451
8582
|
}
|
|
8583
|
+
ignoreMutation(mutation) {
|
|
8584
|
+
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
|
|
8585
|
+
}
|
|
8586
|
+
destroy() {
|
|
8587
|
+
if (this.spec.destroy)
|
|
8588
|
+
this.spec.destroy();
|
|
8589
|
+
super.destroy();
|
|
8590
|
+
}
|
|
8452
8591
|
}
|
|
8453
8592
|
// Node view descs are the main, most common type of view desc, and
|
|
8454
8593
|
// correspond to an actual node in the document. Unlike mark descs,
|
|
@@ -8488,7 +8627,8 @@ class NodeViewDesc extends ViewDesc {
|
|
|
8488
8627
|
throw new RangeError("Text must be rendered as a DOM text node");
|
|
8489
8628
|
}
|
|
8490
8629
|
else if (!dom) {
|
|
8491
|
-
|
|
8630
|
+
let spec = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node), null, node.attrs);
|
|
8631
|
+
({ dom, contentDOM } = spec);
|
|
8492
8632
|
}
|
|
8493
8633
|
if (!contentDOM && !node.isText && dom.nodeName != "BR") { // Chrome gets confused by <br contenteditable=false>
|
|
8494
8634
|
if (!dom.hasAttribute("contenteditable"))
|
|
@@ -8600,8 +8740,7 @@ class NodeViewDesc extends ViewDesc {
|
|
|
8600
8740
|
let { from, to } = view.state.selection;
|
|
8601
8741
|
if (!(view.state.selection instanceof TextSelection) || from < pos || to > pos + this.node.content.size)
|
|
8602
8742
|
return null;
|
|
8603
|
-
let
|
|
8604
|
-
let textNode = nearbyTextNode(sel.focusNode, sel.focusOffset);
|
|
8743
|
+
let textNode = view.input.compositionNode;
|
|
8605
8744
|
if (!textNode || !this.dom.contains(textNode.parentNode))
|
|
8606
8745
|
return null;
|
|
8607
8746
|
if (this.node.inlineContent) {
|
|
@@ -8675,10 +8814,11 @@ class NodeViewDesc extends ViewDesc {
|
|
|
8675
8814
|
}
|
|
8676
8815
|
// Remove selected node marking from this node.
|
|
8677
8816
|
deselectNode() {
|
|
8678
|
-
if (this.nodeDOM.nodeType == 1)
|
|
8817
|
+
if (this.nodeDOM.nodeType == 1) {
|
|
8679
8818
|
this.nodeDOM.classList.remove("ProseMirror-selectednode");
|
|
8680
|
-
|
|
8681
|
-
|
|
8819
|
+
if (this.contentDOM || !this.node.type.spec.draggable)
|
|
8820
|
+
this.dom.removeAttribute("draggable");
|
|
8821
|
+
}
|
|
8682
8822
|
}
|
|
8683
8823
|
get domAtom() { return this.node.isAtom; }
|
|
8684
8824
|
}
|
|
@@ -8743,6 +8883,7 @@ class TextViewDesc extends NodeViewDesc {
|
|
|
8743
8883
|
this.dirty = NODE_DIRTY;
|
|
8744
8884
|
}
|
|
8745
8885
|
get domAtom() { return false; }
|
|
8886
|
+
isText(text) { return this.node.text == text; }
|
|
8746
8887
|
}
|
|
8747
8888
|
// A dummy desc used to tag trailing BR or IMG nodes created to work
|
|
8748
8889
|
// around contentEditable terribleness.
|
|
@@ -8766,7 +8907,7 @@ class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
8766
8907
|
update(node, outerDeco, innerDeco, view) {
|
|
8767
8908
|
if (this.dirty == NODE_DIRTY)
|
|
8768
8909
|
return false;
|
|
8769
|
-
if (this.spec.update) {
|
|
8910
|
+
if (this.spec.update && (this.node.type == node.type || this.spec.multiType)) {
|
|
8770
8911
|
let result = this.spec.update(node, outerDeco, innerDeco);
|
|
8771
8912
|
if (result)
|
|
8772
8913
|
this.updateInner(node, outerDeco, innerDeco, view);
|
|
@@ -8785,9 +8926,9 @@ class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
8785
8926
|
deselectNode() {
|
|
8786
8927
|
this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode();
|
|
8787
8928
|
}
|
|
8788
|
-
setSelection(anchor, head,
|
|
8789
|
-
this.spec.setSelection ? this.spec.setSelection(anchor, head, root)
|
|
8790
|
-
: super.setSelection(anchor, head,
|
|
8929
|
+
setSelection(anchor, head, view, force) {
|
|
8930
|
+
this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root)
|
|
8931
|
+
: super.setSelection(anchor, head, view, force);
|
|
8791
8932
|
}
|
|
8792
8933
|
destroy() {
|
|
8793
8934
|
if (this.spec.destroy)
|
|
@@ -9084,6 +9225,7 @@ class ViewTreeUpdater {
|
|
|
9084
9225
|
return true;
|
|
9085
9226
|
}
|
|
9086
9227
|
else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
|
|
9228
|
+
this.destroyBetween(this.index, i);
|
|
9087
9229
|
this.top.children[this.index] = updated;
|
|
9088
9230
|
if (updated.contentDOM) {
|
|
9089
9231
|
updated.dirty = CONTENT_DIRTY;
|
|
@@ -9103,7 +9245,8 @@ class ViewTreeUpdater {
|
|
|
9103
9245
|
// identical content, move over its children.
|
|
9104
9246
|
recreateWrapper(next, node, outerDeco, innerDeco, view, pos) {
|
|
9105
9247
|
if (next.dirty || node.isAtom || !next.children.length ||
|
|
9106
|
-
!next.node.content.eq(node.content)
|
|
9248
|
+
!next.node.content.eq(node.content) ||
|
|
9249
|
+
!sameOuterDeco(outerDeco, next.outerDeco) || !innerDeco.eq(next.innerDeco))
|
|
9107
9250
|
return null;
|
|
9108
9251
|
let wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
|
|
9109
9252
|
if (wrapper.contentDOM) {
|
|
@@ -9312,25 +9455,6 @@ function iosHacks(dom) {
|
|
|
9312
9455
|
dom.style.cssText = oldCSS;
|
|
9313
9456
|
}
|
|
9314
9457
|
}
|
|
9315
|
-
function nearbyTextNode(node, offset) {
|
|
9316
|
-
for (;;) {
|
|
9317
|
-
if (node.nodeType == 3)
|
|
9318
|
-
return node;
|
|
9319
|
-
if (node.nodeType == 1 && offset > 0) {
|
|
9320
|
-
if (node.childNodes.length > offset && node.childNodes[offset].nodeType == 3)
|
|
9321
|
-
return node.childNodes[offset];
|
|
9322
|
-
node = node.childNodes[offset - 1];
|
|
9323
|
-
offset = nodeSize(node);
|
|
9324
|
-
}
|
|
9325
|
-
else if (node.nodeType == 1 && offset < node.childNodes.length) {
|
|
9326
|
-
node = node.childNodes[offset];
|
|
9327
|
-
offset = 0;
|
|
9328
|
-
}
|
|
9329
|
-
else {
|
|
9330
|
-
return null;
|
|
9331
|
-
}
|
|
9332
|
-
}
|
|
9333
|
-
}
|
|
9334
9458
|
// Find a piece of text in an inline fragment, overlapping from-to
|
|
9335
9459
|
function findTextInFragment(frag, text, from, to) {
|
|
9336
9460
|
for (let i = 0, pos = 0; i < frag.childCount && pos <= to;) {
|
|
@@ -9393,9 +9517,9 @@ function selectionFromDOM(view, origin = null) {
|
|
|
9393
9517
|
let head = view.docView.posFromDOM(domSel.focusNode, domSel.focusOffset, 1);
|
|
9394
9518
|
if (head < 0)
|
|
9395
9519
|
return null;
|
|
9396
|
-
let $head = doc.resolve(head),
|
|
9520
|
+
let $head = doc.resolve(head), anchor, selection;
|
|
9397
9521
|
if (selectionCollapsed(domSel)) {
|
|
9398
|
-
|
|
9522
|
+
anchor = head;
|
|
9399
9523
|
while (nearestDesc && !nearestDesc.node)
|
|
9400
9524
|
nearestDesc = nearestDesc.parent;
|
|
9401
9525
|
let nearestDescNode = nearestDesc.node;
|
|
@@ -9406,11 +9530,25 @@ function selectionFromDOM(view, origin = null) {
|
|
|
9406
9530
|
}
|
|
9407
9531
|
}
|
|
9408
9532
|
else {
|
|
9409
|
-
|
|
9533
|
+
if (domSel instanceof view.dom.ownerDocument.defaultView.Selection && domSel.rangeCount > 1) {
|
|
9534
|
+
let min = head, max = head;
|
|
9535
|
+
for (let i = 0; i < domSel.rangeCount; i++) {
|
|
9536
|
+
let range = domSel.getRangeAt(i);
|
|
9537
|
+
min = Math.min(min, view.docView.posFromDOM(range.startContainer, range.startOffset, 1));
|
|
9538
|
+
max = Math.max(max, view.docView.posFromDOM(range.endContainer, range.endOffset, -1));
|
|
9539
|
+
}
|
|
9540
|
+
if (min < 0)
|
|
9541
|
+
return null;
|
|
9542
|
+
[anchor, head] = max == view.state.selection.anchor ? [max, min] : [min, max];
|
|
9543
|
+
$head = doc.resolve(head);
|
|
9544
|
+
}
|
|
9545
|
+
else {
|
|
9546
|
+
anchor = view.docView.posFromDOM(domSel.anchorNode, domSel.anchorOffset, 1);
|
|
9547
|
+
}
|
|
9410
9548
|
if (anchor < 0)
|
|
9411
9549
|
return null;
|
|
9412
|
-
$anchor = doc.resolve(anchor);
|
|
9413
9550
|
}
|
|
9551
|
+
let $anchor = doc.resolve(anchor);
|
|
9414
9552
|
if (!selection) {
|
|
9415
9553
|
let bias = origin == "pointer" || (view.state.selection.head < $head.pos && !inWidget) ? 1 : -1;
|
|
9416
9554
|
selection = selectionBetween(view, $anchor, $head, bias);
|
|
@@ -9450,7 +9588,7 @@ function selectionToDOM(view, force = false) {
|
|
|
9450
9588
|
if (!sel.empty && !sel.$from.parent.inlineContent)
|
|
9451
9589
|
resetEditableTo = temporarilyEditableNear(view, sel.to);
|
|
9452
9590
|
}
|
|
9453
|
-
view.docView.setSelection(anchor, head, view
|
|
9591
|
+
view.docView.setSelection(anchor, head, view, force);
|
|
9454
9592
|
if (brokenSelectBetweenUneditable) {
|
|
9455
9593
|
if (resetEditableFrom)
|
|
9456
9594
|
resetEditable(resetEditableFrom);
|
|
@@ -9519,12 +9657,14 @@ function removeClassOnSelectionChange(view) {
|
|
|
9519
9657
|
}
|
|
9520
9658
|
function selectCursorWrapper(view) {
|
|
9521
9659
|
let domSel = view.domSelection(), range = document.createRange();
|
|
9660
|
+
if (!domSel)
|
|
9661
|
+
return;
|
|
9522
9662
|
let node = view.cursorWrapper.dom, img = node.nodeName == "IMG";
|
|
9523
9663
|
if (img)
|
|
9524
|
-
range.
|
|
9664
|
+
range.setStart(node.parentNode, domIndex(node) + 1);
|
|
9525
9665
|
else
|
|
9526
|
-
range.
|
|
9527
|
-
range.collapse(
|
|
9666
|
+
range.setStart(node, 0);
|
|
9667
|
+
range.collapse(true);
|
|
9528
9668
|
domSel.removeAllRanges();
|
|
9529
9669
|
domSel.addRange(range);
|
|
9530
9670
|
// Kludge to kill 'control selection' in IE11 when selecting an
|
|
@@ -9812,6 +9952,8 @@ function setSelFocus(view, node, offset) {
|
|
|
9812
9952
|
}
|
|
9813
9953
|
}
|
|
9814
9954
|
let sel = view.domSelection();
|
|
9955
|
+
if (!sel)
|
|
9956
|
+
return;
|
|
9815
9957
|
if (selectionCollapsed(sel)) {
|
|
9816
9958
|
let range = document.createRange();
|
|
9817
9959
|
range.setEnd(node, offset);
|
|
@@ -9994,7 +10136,7 @@ function serializeForClipboard(view, slice) {
|
|
|
9994
10136
|
firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
|
|
9995
10137
|
let text = view.someProp("clipboardTextSerializer", f => f(slice, view)) ||
|
|
9996
10138
|
slice.content.textBetween(0, slice.content.size, "\n\n");
|
|
9997
|
-
return { dom: wrap, text };
|
|
10139
|
+
return { dom: wrap, text, slice };
|
|
9998
10140
|
}
|
|
9999
10141
|
// Read a slice of content from the clipboard (or drop data).
|
|
10000
10142
|
function parseFromClipboard(view, text, html, plainText, $context) {
|
|
@@ -10166,6 +10308,18 @@ let _detachedDoc = null;
|
|
|
10166
10308
|
function detachedDoc() {
|
|
10167
10309
|
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
|
|
10168
10310
|
}
|
|
10311
|
+
let _policy = null;
|
|
10312
|
+
function maybeWrapTrusted(html) {
|
|
10313
|
+
let trustedTypes = window.trustedTypes;
|
|
10314
|
+
if (!trustedTypes)
|
|
10315
|
+
return html;
|
|
10316
|
+
// With the require-trusted-types-for CSP, Chrome will block
|
|
10317
|
+
// innerHTML, even on a detached document. This wraps the string in
|
|
10318
|
+
// a way that makes the browser allow us to use its parser again.
|
|
10319
|
+
if (!_policy)
|
|
10320
|
+
_policy = trustedTypes.createPolicy("ProseMirrorClipboard", { createHTML: (s) => s });
|
|
10321
|
+
return _policy.createHTML(html);
|
|
10322
|
+
}
|
|
10169
10323
|
function readHTML(html) {
|
|
10170
10324
|
let metas = /^(\s*<meta [^>]*>)*/.exec(html);
|
|
10171
10325
|
if (metas)
|
|
@@ -10174,7 +10328,7 @@ function readHTML(html) {
|
|
|
10174
10328
|
let firstTag = /<([a-z][^>\s]+)/i.exec(html), wrap;
|
|
10175
10329
|
if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()])
|
|
10176
10330
|
html = wrap.map(n => "<" + n + ">").join("") + html + wrap.map(n => "</" + n + ">").reverse().join("");
|
|
10177
|
-
elt.innerHTML = html;
|
|
10331
|
+
elt.innerHTML = maybeWrapTrusted(html);
|
|
10178
10332
|
if (wrap)
|
|
10179
10333
|
for (let i = 0; i < wrap.length; i++)
|
|
10180
10334
|
elt = elt.querySelector(wrap[i]) || elt;
|
|
@@ -10233,8 +10387,9 @@ class InputState {
|
|
|
10233
10387
|
this.lastIOSEnterFallbackTimeout = -1;
|
|
10234
10388
|
this.lastFocus = 0;
|
|
10235
10389
|
this.lastTouch = 0;
|
|
10236
|
-
this.
|
|
10390
|
+
this.lastChromeDelete = 0;
|
|
10237
10391
|
this.composing = false;
|
|
10392
|
+
this.compositionNode = null;
|
|
10238
10393
|
this.composingTimeout = -1;
|
|
10239
10394
|
this.compositionNodes = [];
|
|
10240
10395
|
this.compositionEndedAt = -2e8;
|
|
@@ -10377,6 +10532,8 @@ function runHandlerOnContext(view, propName, pos, inside, event) {
|
|
|
10377
10532
|
function updateSelection(view, selection, origin) {
|
|
10378
10533
|
if (!view.focused)
|
|
10379
10534
|
view.focus();
|
|
10535
|
+
if (view.state.selection.eq(selection))
|
|
10536
|
+
return;
|
|
10380
10537
|
let tr = view.state.tr.setSelection(selection);
|
|
10381
10538
|
if (origin == "pointer")
|
|
10382
10539
|
tr.setMeta("pointer", true);
|
|
@@ -10510,7 +10667,7 @@ class MouseDown {
|
|
|
10510
10667
|
}
|
|
10511
10668
|
const target = flushed ? null : event.target;
|
|
10512
10669
|
const targetDesc = target ? view.docView.nearestDesc(target, true) : null;
|
|
10513
|
-
this.target = targetDesc ? targetDesc.dom : null;
|
|
10670
|
+
this.target = targetDesc && targetDesc.dom.nodeType == 1 ? targetDesc.dom : null;
|
|
10514
10671
|
let { selection } = view.state;
|
|
10515
10672
|
if (event.button == 0 &&
|
|
10516
10673
|
targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false ||
|
|
@@ -10631,8 +10788,8 @@ const timeoutComposition = android ? 5000 : -1;
|
|
|
10631
10788
|
editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
10632
10789
|
if (!view.composing) {
|
|
10633
10790
|
view.domObserver.flush();
|
|
10634
|
-
let { state } = view, $pos = state.selection.$
|
|
10635
|
-
if (state.selection
|
|
10791
|
+
let { state } = view, $pos = state.selection.$to;
|
|
10792
|
+
if (state.selection instanceof TextSelection &&
|
|
10636
10793
|
(state.storedMarks ||
|
|
10637
10794
|
(!$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some(m => m.type.spec.inclusive === false)))) {
|
|
10638
10795
|
// Need to wrap the cursor in mark nodes different from the ones in the DOM context
|
|
@@ -10641,7 +10798,7 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
|
10641
10798
|
view.markCursor = null;
|
|
10642
10799
|
}
|
|
10643
10800
|
else {
|
|
10644
|
-
endComposition(view);
|
|
10801
|
+
endComposition(view, !state.selection.empty);
|
|
10645
10802
|
// In firefox, if the cursor is after but outside a marked node,
|
|
10646
10803
|
// the inserted text won't inherit the marks. So this moves it
|
|
10647
10804
|
// inside if necessary.
|
|
@@ -10652,7 +10809,9 @@ editHandlers.compositionstart = editHandlers.compositionupdate = view => {
|
|
|
10652
10809
|
if (!before)
|
|
10653
10810
|
break;
|
|
10654
10811
|
if (before.nodeType == 3) {
|
|
10655
|
-
view.domSelection()
|
|
10812
|
+
let sel = view.domSelection();
|
|
10813
|
+
if (sel)
|
|
10814
|
+
sel.collapse(before, before.nodeValue.length);
|
|
10656
10815
|
break;
|
|
10657
10816
|
}
|
|
10658
10817
|
else {
|
|
@@ -10671,6 +10830,7 @@ editHandlers.compositionend = (view, event) => {
|
|
|
10671
10830
|
view.input.composing = false;
|
|
10672
10831
|
view.input.compositionEndedAt = event.timeStamp;
|
|
10673
10832
|
view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
|
|
10833
|
+
view.input.compositionNode = null;
|
|
10674
10834
|
if (view.input.compositionPendingChanges)
|
|
10675
10835
|
Promise.resolve().then(() => view.domObserver.flush());
|
|
10676
10836
|
view.input.compositionID++;
|
|
@@ -10690,6 +10850,27 @@ function clearComposition(view) {
|
|
|
10690
10850
|
while (view.input.compositionNodes.length > 0)
|
|
10691
10851
|
view.input.compositionNodes.pop().markParentsDirty();
|
|
10692
10852
|
}
|
|
10853
|
+
function findCompositionNode(view) {
|
|
10854
|
+
let sel = view.domSelectionRange();
|
|
10855
|
+
if (!sel.focusNode)
|
|
10856
|
+
return null;
|
|
10857
|
+
let textBefore = textNodeBefore$1(sel.focusNode, sel.focusOffset);
|
|
10858
|
+
let textAfter = textNodeAfter$1(sel.focusNode, sel.focusOffset);
|
|
10859
|
+
if (textBefore && textAfter && textBefore != textAfter) {
|
|
10860
|
+
let descAfter = textAfter.pmViewDesc, lastChanged = view.domObserver.lastChangedTextNode;
|
|
10861
|
+
if (textBefore == lastChanged || textAfter == lastChanged)
|
|
10862
|
+
return lastChanged;
|
|
10863
|
+
if (!descAfter || !descAfter.isText(textAfter.nodeValue)) {
|
|
10864
|
+
return textAfter;
|
|
10865
|
+
}
|
|
10866
|
+
else if (view.input.compositionNode == textAfter) {
|
|
10867
|
+
let descBefore = textBefore.pmViewDesc;
|
|
10868
|
+
if (!(!descBefore || !descBefore.isText(textBefore.nodeValue)))
|
|
10869
|
+
return textAfter;
|
|
10870
|
+
}
|
|
10871
|
+
}
|
|
10872
|
+
return textBefore || textAfter;
|
|
10873
|
+
}
|
|
10693
10874
|
function timestampFromCustomEvent() {
|
|
10694
10875
|
let event = document.createEvent("Event");
|
|
10695
10876
|
event.initEvent("event", true, true);
|
|
@@ -10698,15 +10879,17 @@ function timestampFromCustomEvent() {
|
|
|
10698
10879
|
/**
|
|
10699
10880
|
@internal
|
|
10700
10881
|
*/
|
|
10701
|
-
function endComposition(view,
|
|
10882
|
+
function endComposition(view, restarting = false) {
|
|
10702
10883
|
if (android && view.domObserver.flushingSoon >= 0)
|
|
10703
10884
|
return;
|
|
10704
10885
|
view.domObserver.forceFlush();
|
|
10705
10886
|
clearComposition(view);
|
|
10706
|
-
if (
|
|
10887
|
+
if (restarting || view.docView && view.docView.dirty) {
|
|
10707
10888
|
let sel = selectionFromDOM(view);
|
|
10708
10889
|
if (sel && !sel.eq(view.state.selection))
|
|
10709
10890
|
view.dispatch(view.state.tr.setSelection(sel));
|
|
10891
|
+
else if ((view.markCursor || restarting) && !view.state.selection.empty)
|
|
10892
|
+
view.dispatch(view.state.tr.deleteSelection());
|
|
10710
10893
|
else
|
|
10711
10894
|
view.updateState(view.state);
|
|
10712
10895
|
return true;
|
|
@@ -10845,8 +11028,11 @@ handlers.dragstart = (view, _event) => {
|
|
|
10845
11028
|
if (desc && desc.node.type.spec.draggable && desc != view.docView)
|
|
10846
11029
|
node = NodeSelection.create(view.state.doc, desc.posBefore);
|
|
10847
11030
|
}
|
|
10848
|
-
let
|
|
10849
|
-
|
|
11031
|
+
let draggedSlice = (node || view.state.selection).content();
|
|
11032
|
+
let { dom, text, slice } = serializeForClipboard(view, draggedSlice);
|
|
11033
|
+
// Pre-120 Chrome versions clear files when calling `clearData` (#1472)
|
|
11034
|
+
if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
|
|
11035
|
+
event.dataTransfer.clearData();
|
|
10850
11036
|
event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
|
|
10851
11037
|
// See https://github.com/ProseMirror/prosemirror/issues/1156
|
|
10852
11038
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
@@ -11360,6 +11546,7 @@ class DecorationSet {
|
|
|
11360
11546
|
}
|
|
11361
11547
|
return result;
|
|
11362
11548
|
}
|
|
11549
|
+
forEachSet(f) { f(this); }
|
|
11363
11550
|
}
|
|
11364
11551
|
/**
|
|
11365
11552
|
The empty set of decorations.
|
|
@@ -11435,6 +11622,10 @@ class DecorationGroup {
|
|
|
11435
11622
|
members.reduce((r, m) => r.concat(m instanceof DecorationSet ? m : m.members), []));
|
|
11436
11623
|
}
|
|
11437
11624
|
}
|
|
11625
|
+
forEachSet(f) {
|
|
11626
|
+
for (let i = 0; i < this.members.length; i++)
|
|
11627
|
+
this.members[i].forEachSet(f);
|
|
11628
|
+
}
|
|
11438
11629
|
}
|
|
11439
11630
|
function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) {
|
|
11440
11631
|
let children = oldChildren.slice();
|
|
@@ -11689,6 +11880,7 @@ class DOMObserver {
|
|
|
11689
11880
|
this.currentSelection = new SelectionState;
|
|
11690
11881
|
this.onCharData = null;
|
|
11691
11882
|
this.suppressingSelectionUpdates = false;
|
|
11883
|
+
this.lastChangedTextNode = null;
|
|
11692
11884
|
this.observer = window.MutationObserver &&
|
|
11693
11885
|
new window.MutationObserver(mutations => {
|
|
11694
11886
|
for (let i = 0; i < mutations.length; i++)
|
|
@@ -11821,15 +12013,23 @@ class DOMObserver {
|
|
|
11821
12013
|
}
|
|
11822
12014
|
}
|
|
11823
12015
|
}
|
|
11824
|
-
if (gecko && added.length
|
|
12016
|
+
if (gecko && added.length) {
|
|
11825
12017
|
let brs = added.filter(n => n.nodeName == "BR");
|
|
11826
12018
|
if (brs.length == 2) {
|
|
11827
|
-
let a
|
|
12019
|
+
let [a, b] = brs;
|
|
11828
12020
|
if (a.parentNode && a.parentNode.parentNode == b.parentNode)
|
|
11829
12021
|
b.remove();
|
|
11830
12022
|
else
|
|
11831
12023
|
a.remove();
|
|
11832
12024
|
}
|
|
12025
|
+
else {
|
|
12026
|
+
let { focusNode } = this.currentSelection;
|
|
12027
|
+
for (let br of brs) {
|
|
12028
|
+
let parent = br.parentNode;
|
|
12029
|
+
if (parent && parent.nodeName == "LI" && (!focusNode || blockParent(view, focusNode) != parent))
|
|
12030
|
+
br.remove();
|
|
12031
|
+
}
|
|
12032
|
+
}
|
|
11833
12033
|
}
|
|
11834
12034
|
let readSel = null;
|
|
11835
12035
|
// If it looks like the browser has reset the selection to the
|
|
@@ -11870,8 +12070,12 @@ class DOMObserver {
|
|
|
11870
12070
|
if (!desc || desc.ignoreMutation(mut))
|
|
11871
12071
|
return null;
|
|
11872
12072
|
if (mut.type == "childList") {
|
|
11873
|
-
for (let i = 0; i < mut.addedNodes.length; i++)
|
|
11874
|
-
|
|
12073
|
+
for (let i = 0; i < mut.addedNodes.length; i++) {
|
|
12074
|
+
let node = mut.addedNodes[i];
|
|
12075
|
+
added.push(node);
|
|
12076
|
+
if (node.nodeType == 3)
|
|
12077
|
+
this.lastChangedTextNode = node;
|
|
12078
|
+
}
|
|
11875
12079
|
if (desc.contentDOM && desc.contentDOM != desc.dom && !desc.contentDOM.contains(mut.target))
|
|
11876
12080
|
return { from: desc.posBefore, to: desc.posAfter };
|
|
11877
12081
|
let prev = mut.previousSibling, next = mut.nextSibling;
|
|
@@ -11898,6 +12102,7 @@ class DOMObserver {
|
|
|
11898
12102
|
return { from: desc.posAtStart - desc.border, to: desc.posAtEnd + desc.border };
|
|
11899
12103
|
}
|
|
11900
12104
|
else { // "characterData"
|
|
12105
|
+
this.lastChangedTextNode = mut.target;
|
|
11901
12106
|
return {
|
|
11902
12107
|
from: desc.posAtStart,
|
|
11903
12108
|
to: desc.posAtEnd,
|
|
@@ -11924,9 +12129,25 @@ function checkCSS(view) {
|
|
|
11924
12129
|
cssCheckWarned = true;
|
|
11925
12130
|
}
|
|
11926
12131
|
}
|
|
12132
|
+
function rangeToSelectionRange(view, range) {
|
|
12133
|
+
let anchorNode = range.startContainer, anchorOffset = range.startOffset;
|
|
12134
|
+
let focusNode = range.endContainer, focusOffset = range.endOffset;
|
|
12135
|
+
let currentAnchor = view.domAtPos(view.state.selection.anchor);
|
|
12136
|
+
// Since such a range doesn't distinguish between anchor and head,
|
|
12137
|
+
// use a heuristic that flips it around if its end matches the
|
|
12138
|
+
// current anchor.
|
|
12139
|
+
if (isEquivalentPosition(currentAnchor.node, currentAnchor.offset, focusNode, focusOffset))
|
|
12140
|
+
[anchorNode, anchorOffset, focusNode, focusOffset] = [focusNode, focusOffset, anchorNode, anchorOffset];
|
|
12141
|
+
return { anchorNode, anchorOffset, focusNode, focusOffset };
|
|
12142
|
+
}
|
|
11927
12143
|
// Used to work around a Safari Selection/shadow DOM bug
|
|
11928
12144
|
// Based on https://github.com/codemirror/dev/issues/414 fix
|
|
11929
|
-
function safariShadowSelectionRange(view) {
|
|
12145
|
+
function safariShadowSelectionRange(view, selection) {
|
|
12146
|
+
if (selection.getComposedRanges) {
|
|
12147
|
+
let range = selection.getComposedRanges(view.root)[0];
|
|
12148
|
+
if (range)
|
|
12149
|
+
return rangeToSelectionRange(view, range);
|
|
12150
|
+
}
|
|
11930
12151
|
let found;
|
|
11931
12152
|
function read(event) {
|
|
11932
12153
|
event.preventDefault();
|
|
@@ -11941,15 +12162,15 @@ function safariShadowSelectionRange(view) {
|
|
|
11941
12162
|
view.dom.addEventListener("beforeinput", read, true);
|
|
11942
12163
|
document.execCommand("indent");
|
|
11943
12164
|
view.dom.removeEventListener("beforeinput", read, true);
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
|
|
11949
|
-
|
|
11950
|
-
|
|
11951
|
-
|
|
11952
|
-
return
|
|
12165
|
+
return found ? rangeToSelectionRange(view, found) : null;
|
|
12166
|
+
}
|
|
12167
|
+
function blockParent(view, node) {
|
|
12168
|
+
for (let p = node.parentNode; p && p != view.dom; p = p.parentNode) {
|
|
12169
|
+
let desc = view.docView.nearestDesc(p, true);
|
|
12170
|
+
if (desc && desc.node.isBlock)
|
|
12171
|
+
return p;
|
|
12172
|
+
}
|
|
12173
|
+
return null;
|
|
11953
12174
|
}
|
|
11954
12175
|
|
|
11955
12176
|
// Note that all referencing and parsing is done with the
|
|
@@ -12067,6 +12288,8 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12067
12288
|
}
|
|
12068
12289
|
view.input.lastKeyCode = null;
|
|
12069
12290
|
let change = findDiff(compare.content, parse.doc.content, parse.from, preferredPos, preferredSide);
|
|
12291
|
+
if (change)
|
|
12292
|
+
view.input.domChangeCount++;
|
|
12070
12293
|
if ((ios && view.input.lastIOSEnter > Date.now() - 225 || android) &&
|
|
12071
12294
|
addedNodes.some(n => n.nodeType == 1 && !isInline.test(n.nodeName)) &&
|
|
12072
12295
|
(!change || change.endA >= change.endB) &&
|
|
@@ -12092,14 +12315,6 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12092
12315
|
return;
|
|
12093
12316
|
}
|
|
12094
12317
|
}
|
|
12095
|
-
// Chrome sometimes leaves the cursor before the inserted text when
|
|
12096
|
-
// composing after a cursor wrapper. This moves it forward.
|
|
12097
|
-
if (chrome && view.cursorWrapper && parse.sel && parse.sel.anchor == view.cursorWrapper.deco.from &&
|
|
12098
|
-
parse.sel.head == parse.sel.anchor) {
|
|
12099
|
-
let size = change.endB - change.start;
|
|
12100
|
-
parse.sel = { anchor: parse.sel.anchor + size, head: parse.sel.anchor + size };
|
|
12101
|
-
}
|
|
12102
|
-
view.input.domChangeCount++;
|
|
12103
12318
|
// Handle the case where overwriting a selection by typing matches
|
|
12104
12319
|
// the start or end of the selected content, creating a change
|
|
12105
12320
|
// that's smaller than what was actually overwritten.
|
|
@@ -12144,17 +12359,17 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12144
12359
|
}
|
|
12145
12360
|
// Same for backspace
|
|
12146
12361
|
if (view.state.selection.anchor > change.start &&
|
|
12147
|
-
|
|
12362
|
+
looksLikeBackspace(doc, change.start, change.endA, $from, $to) &&
|
|
12148
12363
|
view.someProp("handleKeyDown", f => f(view, keyEvent(8, "Backspace")))) {
|
|
12149
12364
|
if (android && chrome)
|
|
12150
12365
|
view.domObserver.suppressSelectionUpdates(); // #820
|
|
12151
12366
|
return;
|
|
12152
12367
|
}
|
|
12153
|
-
// Chrome
|
|
12368
|
+
// Chrome will occasionally, during composition, delete the
|
|
12154
12369
|
// entire composition and then immediately insert it again. This is
|
|
12155
12370
|
// used to detect that situation.
|
|
12156
|
-
if (chrome &&
|
|
12157
|
-
view.input.
|
|
12371
|
+
if (chrome && change.endB == change.start)
|
|
12372
|
+
view.input.lastChromeDelete = Date.now();
|
|
12158
12373
|
// This tries to detect Android virtual keyboard
|
|
12159
12374
|
// enter-and-pick-suggestion action. That sometimes (see issue
|
|
12160
12375
|
// #1059) first fires a DOM mutation, before moving the selection to
|
|
@@ -12205,13 +12420,13 @@ function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
|
12205
12420
|
tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from));
|
|
12206
12421
|
if (parse.sel) {
|
|
12207
12422
|
let sel = resolveSelection(view, tr.doc, parse.sel);
|
|
12208
|
-
// Chrome
|
|
12423
|
+
// Chrome will sometimes, during composition, report the
|
|
12209
12424
|
// selection in the wrong place. If it looks like that is
|
|
12210
12425
|
// happening, don't update the selection.
|
|
12211
12426
|
// Edge just doesn't move the cursor forward when you start typing
|
|
12212
12427
|
// in an empty block or between br nodes.
|
|
12213
|
-
if (sel && !(chrome &&
|
|
12214
|
-
(change.start != change.endB || view.input.
|
|
12428
|
+
if (sel && !(chrome && view.composing && sel.empty &&
|
|
12429
|
+
(change.start != change.endB || view.input.lastChromeDelete < Date.now() - 100) &&
|
|
12215
12430
|
(sel.head == chFrom || sel.head == tr.mapping.map(chTo) - 1) ||
|
|
12216
12431
|
ie$1 && sel.empty && sel.head == chFrom))
|
|
12217
12432
|
tr.setSelection(sel);
|
|
@@ -12256,14 +12471,18 @@ function isMarkChange(cur, prev) {
|
|
|
12256
12471
|
if (Fragment.from(updated).eq(cur))
|
|
12257
12472
|
return { mark, type };
|
|
12258
12473
|
}
|
|
12259
|
-
function
|
|
12260
|
-
if (
|
|
12261
|
-
|
|
12262
|
-
end - start <= $newEnd.pos - $newStart.pos ||
|
|
12474
|
+
function looksLikeBackspace(old, start, end, $newStart, $newEnd) {
|
|
12475
|
+
if ( // The content must have shrunk
|
|
12476
|
+
end - start <= $newEnd.pos - $newStart.pos ||
|
|
12263
12477
|
// newEnd must point directly at or after the end of the block that newStart points into
|
|
12264
12478
|
skipClosingAndOpening($newStart, true, false) < $newEnd.pos)
|
|
12265
12479
|
return false;
|
|
12266
12480
|
let $start = old.resolve(start);
|
|
12481
|
+
// Handle the case where, rather than joining blocks, the change just removed an entire block
|
|
12482
|
+
if (!$newStart.parent.isTextblock) {
|
|
12483
|
+
let after = $start.nodeAfter;
|
|
12484
|
+
return after != null && end == start + after.nodeSize;
|
|
12485
|
+
}
|
|
12267
12486
|
// Start must be at the end of a block
|
|
12268
12487
|
if ($start.parentOffset < $start.parent.content.size || !$start.parent.isTextblock)
|
|
12269
12488
|
return false;
|
|
@@ -12501,8 +12720,10 @@ class EditorView {
|
|
|
12501
12720
|
// tracks that and forces a selection reset when our update
|
|
12502
12721
|
// did write to the node.
|
|
12503
12722
|
let chromeKludge = chrome ? (this.trackWrites = this.domSelectionRange().focusNode) : null;
|
|
12723
|
+
if (this.composing)
|
|
12724
|
+
this.input.compositionNode = findCompositionNode(this);
|
|
12504
12725
|
if (redraw || !this.docView.update(state.doc, outerDeco, innerDeco, this)) {
|
|
12505
|
-
this.docView.updateOuterDeco(
|
|
12726
|
+
this.docView.updateOuterDeco(outerDeco);
|
|
12506
12727
|
this.docView.destroy();
|
|
12507
12728
|
this.docView = docViewDesc(state.doc, outerDeco, innerDeco, this.dom, this);
|
|
12508
12729
|
}
|
|
@@ -12779,6 +13000,7 @@ class EditorView {
|
|
|
12779
13000
|
}
|
|
12780
13001
|
this.docView.destroy();
|
|
12781
13002
|
this.docView = null;
|
|
13003
|
+
clearReusedRange();
|
|
12782
13004
|
}
|
|
12783
13005
|
/**
|
|
12784
13006
|
This is true when the view has been
|
|
@@ -12814,8 +13036,11 @@ class EditorView {
|
|
|
12814
13036
|
@internal
|
|
12815
13037
|
*/
|
|
12816
13038
|
domSelectionRange() {
|
|
12817
|
-
|
|
12818
|
-
|
|
13039
|
+
let sel = this.domSelection();
|
|
13040
|
+
if (!sel)
|
|
13041
|
+
return { focusNode: null, focusOffset: 0, anchorNode: null, anchorOffset: 0 };
|
|
13042
|
+
return safari && this.root.nodeType === 11 &&
|
|
13043
|
+
deepActiveElement(this.dom.ownerDocument) == this.dom && safariShadowSelectionRange(this, sel) || sel;
|
|
12819
13044
|
}
|
|
12820
13045
|
/**
|
|
12821
13046
|
@internal
|
|
@@ -12851,7 +13076,7 @@ function updateCursorWrapper(view) {
|
|
|
12851
13076
|
dom.className = "ProseMirror-separator";
|
|
12852
13077
|
dom.setAttribute("mark-placeholder", "true");
|
|
12853
13078
|
dom.setAttribute("alt", "");
|
|
12854
|
-
view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.
|
|
13079
|
+
view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.from, dom, { raw: true, marks: view.markCursor }) };
|
|
12855
13080
|
}
|
|
12856
13081
|
else {
|
|
12857
13082
|
view.cursorWrapper = null;
|