@codemirror/view 6.18.1 → 6.20.0
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 +30 -0
- package/dist/index.cjs +524 -482
- package/dist/index.d.cts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +524 -483
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -579,7 +579,7 @@ function replaceRange(parent, fromI, fromOff, toI, toOff, insert, breakAtStart,
|
|
|
579
579
|
if (toI < children.length) {
|
|
580
580
|
let after = children[toI];
|
|
581
581
|
// Make sure the end of the child after the update is preserved in `after`
|
|
582
|
-
if (after && toOff < after.length) {
|
|
582
|
+
if (after && (toOff < after.length || after.breakAfter && (last === null || last === void 0 ? void 0 : last.breakAfter))) {
|
|
583
583
|
// If we're splitting a child, separate part of it to avoid that
|
|
584
584
|
// being mangled when updating the child before the update.
|
|
585
585
|
if (fromI == toI) {
|
|
@@ -1091,6 +1091,236 @@ function getAttrs(dom) {
|
|
|
1091
1091
|
return attrs;
|
|
1092
1092
|
}
|
|
1093
1093
|
|
|
1094
|
+
class LineView extends ContentView {
|
|
1095
|
+
constructor() {
|
|
1096
|
+
super(...arguments);
|
|
1097
|
+
this.children = [];
|
|
1098
|
+
this.length = 0;
|
|
1099
|
+
this.prevAttrs = undefined;
|
|
1100
|
+
this.attrs = null;
|
|
1101
|
+
this.breakAfter = 0;
|
|
1102
|
+
}
|
|
1103
|
+
// Consumes source
|
|
1104
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
1105
|
+
if (source) {
|
|
1106
|
+
if (!(source instanceof LineView))
|
|
1107
|
+
return false;
|
|
1108
|
+
if (!this.dom)
|
|
1109
|
+
source.transferDOM(this); // Reuse source.dom when appropriate
|
|
1110
|
+
}
|
|
1111
|
+
if (hasStart)
|
|
1112
|
+
this.setDeco(source ? source.attrs : null);
|
|
1113
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart, openEnd);
|
|
1114
|
+
return true;
|
|
1115
|
+
}
|
|
1116
|
+
split(at) {
|
|
1117
|
+
let end = new LineView;
|
|
1118
|
+
end.breakAfter = this.breakAfter;
|
|
1119
|
+
if (this.length == 0)
|
|
1120
|
+
return end;
|
|
1121
|
+
let { i, off } = this.childPos(at);
|
|
1122
|
+
if (off) {
|
|
1123
|
+
end.append(this.children[i].split(off), 0);
|
|
1124
|
+
this.children[i].merge(off, this.children[i].length, null, false, 0, 0);
|
|
1125
|
+
i++;
|
|
1126
|
+
}
|
|
1127
|
+
for (let j = i; j < this.children.length; j++)
|
|
1128
|
+
end.append(this.children[j], 0);
|
|
1129
|
+
while (i > 0 && this.children[i - 1].length == 0)
|
|
1130
|
+
this.children[--i].destroy();
|
|
1131
|
+
this.children.length = i;
|
|
1132
|
+
this.markDirty();
|
|
1133
|
+
this.length = at;
|
|
1134
|
+
return end;
|
|
1135
|
+
}
|
|
1136
|
+
transferDOM(other) {
|
|
1137
|
+
if (!this.dom)
|
|
1138
|
+
return;
|
|
1139
|
+
this.markDirty();
|
|
1140
|
+
other.setDOM(this.dom);
|
|
1141
|
+
other.prevAttrs = this.prevAttrs === undefined ? this.attrs : this.prevAttrs;
|
|
1142
|
+
this.prevAttrs = undefined;
|
|
1143
|
+
this.dom = null;
|
|
1144
|
+
}
|
|
1145
|
+
setDeco(attrs) {
|
|
1146
|
+
if (!attrsEq(this.attrs, attrs)) {
|
|
1147
|
+
if (this.dom) {
|
|
1148
|
+
this.prevAttrs = this.attrs;
|
|
1149
|
+
this.markDirty();
|
|
1150
|
+
}
|
|
1151
|
+
this.attrs = attrs;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
append(child, openStart) {
|
|
1155
|
+
joinInlineInto(this, child, openStart);
|
|
1156
|
+
}
|
|
1157
|
+
// Only called when building a line view in ContentBuilder
|
|
1158
|
+
addLineDeco(deco) {
|
|
1159
|
+
let attrs = deco.spec.attributes, cls = deco.spec.class;
|
|
1160
|
+
if (attrs)
|
|
1161
|
+
this.attrs = combineAttrs(attrs, this.attrs || {});
|
|
1162
|
+
if (cls)
|
|
1163
|
+
this.attrs = combineAttrs({ class: cls }, this.attrs || {});
|
|
1164
|
+
}
|
|
1165
|
+
domAtPos(pos) {
|
|
1166
|
+
return inlineDOMAtPos(this, pos);
|
|
1167
|
+
}
|
|
1168
|
+
reuseDOM(node) {
|
|
1169
|
+
if (node.nodeName == "DIV") {
|
|
1170
|
+
this.setDOM(node);
|
|
1171
|
+
this.flags |= 4 /* ViewFlag.AttrsDirty */ | 2 /* ViewFlag.NodeDirty */;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
sync(view, track) {
|
|
1175
|
+
var _a;
|
|
1176
|
+
if (!this.dom) {
|
|
1177
|
+
this.setDOM(document.createElement("div"));
|
|
1178
|
+
this.dom.className = "cm-line";
|
|
1179
|
+
this.prevAttrs = this.attrs ? null : undefined;
|
|
1180
|
+
}
|
|
1181
|
+
else if (this.flags & 4 /* ViewFlag.AttrsDirty */) {
|
|
1182
|
+
clearAttributes(this.dom);
|
|
1183
|
+
this.dom.className = "cm-line";
|
|
1184
|
+
this.prevAttrs = this.attrs ? null : undefined;
|
|
1185
|
+
}
|
|
1186
|
+
if (this.prevAttrs !== undefined) {
|
|
1187
|
+
updateAttrs(this.dom, this.prevAttrs, this.attrs);
|
|
1188
|
+
this.dom.classList.add("cm-line");
|
|
1189
|
+
this.prevAttrs = undefined;
|
|
1190
|
+
}
|
|
1191
|
+
super.sync(view, track);
|
|
1192
|
+
let last = this.dom.lastChild;
|
|
1193
|
+
while (last && ContentView.get(last) instanceof MarkView)
|
|
1194
|
+
last = last.lastChild;
|
|
1195
|
+
if (!last || !this.length ||
|
|
1196
|
+
last.nodeName != "BR" && ((_a = ContentView.get(last)) === null || _a === void 0 ? void 0 : _a.isEditable) == false &&
|
|
1197
|
+
(!browser.ios || !this.children.some(ch => ch instanceof TextView))) {
|
|
1198
|
+
let hack = document.createElement("BR");
|
|
1199
|
+
hack.cmIgnore = true;
|
|
1200
|
+
this.dom.appendChild(hack);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
measureTextSize() {
|
|
1204
|
+
if (this.children.length == 0 || this.length > 20)
|
|
1205
|
+
return null;
|
|
1206
|
+
let totalWidth = 0, textHeight;
|
|
1207
|
+
for (let child of this.children) {
|
|
1208
|
+
if (!(child instanceof TextView) || /[^ -~]/.test(child.text))
|
|
1209
|
+
return null;
|
|
1210
|
+
let rects = clientRectsFor(child.dom);
|
|
1211
|
+
if (rects.length != 1)
|
|
1212
|
+
return null;
|
|
1213
|
+
totalWidth += rects[0].width;
|
|
1214
|
+
textHeight = rects[0].height;
|
|
1215
|
+
}
|
|
1216
|
+
return !totalWidth ? null : {
|
|
1217
|
+
lineHeight: this.dom.getBoundingClientRect().height,
|
|
1218
|
+
charWidth: totalWidth / this.length,
|
|
1219
|
+
textHeight
|
|
1220
|
+
};
|
|
1221
|
+
}
|
|
1222
|
+
coordsAt(pos, side) {
|
|
1223
|
+
let rect = coordsInChildren(this, pos, side);
|
|
1224
|
+
// Correct rectangle height for empty lines when the returned
|
|
1225
|
+
// height is larger than the text height.
|
|
1226
|
+
if (!this.children.length && rect && this.parent) {
|
|
1227
|
+
let { heightOracle } = this.parent.view.viewState, height = rect.bottom - rect.top;
|
|
1228
|
+
if (Math.abs(height - heightOracle.lineHeight) < 2 && heightOracle.textHeight < height) {
|
|
1229
|
+
let dist = (height - heightOracle.textHeight) / 2;
|
|
1230
|
+
return { top: rect.top + dist, bottom: rect.bottom - dist, left: rect.left, right: rect.left };
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
return rect;
|
|
1234
|
+
}
|
|
1235
|
+
become(_other) { return false; }
|
|
1236
|
+
covers() { return true; }
|
|
1237
|
+
static find(docView, pos) {
|
|
1238
|
+
for (let i = 0, off = 0; i < docView.children.length; i++) {
|
|
1239
|
+
let block = docView.children[i], end = off + block.length;
|
|
1240
|
+
if (end >= pos) {
|
|
1241
|
+
if (block instanceof LineView)
|
|
1242
|
+
return block;
|
|
1243
|
+
if (end > pos)
|
|
1244
|
+
break;
|
|
1245
|
+
}
|
|
1246
|
+
off = end + block.breakAfter;
|
|
1247
|
+
}
|
|
1248
|
+
return null;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
class BlockWidgetView extends ContentView {
|
|
1252
|
+
constructor(widget, length, deco) {
|
|
1253
|
+
super();
|
|
1254
|
+
this.widget = widget;
|
|
1255
|
+
this.length = length;
|
|
1256
|
+
this.deco = deco;
|
|
1257
|
+
this.breakAfter = 0;
|
|
1258
|
+
this.prevWidget = null;
|
|
1259
|
+
}
|
|
1260
|
+
merge(from, to, source, _takeDeco, openStart, openEnd) {
|
|
1261
|
+
if (source && (!(source instanceof BlockWidgetView) || !this.widget.compare(source.widget) ||
|
|
1262
|
+
from > 0 && openStart <= 0 || to < this.length && openEnd <= 0))
|
|
1263
|
+
return false;
|
|
1264
|
+
this.length = from + (source ? source.length : 0) + (this.length - to);
|
|
1265
|
+
return true;
|
|
1266
|
+
}
|
|
1267
|
+
domAtPos(pos) {
|
|
1268
|
+
return pos == 0 ? DOMPos.before(this.dom) : DOMPos.after(this.dom, pos == this.length);
|
|
1269
|
+
}
|
|
1270
|
+
split(at) {
|
|
1271
|
+
let len = this.length - at;
|
|
1272
|
+
this.length = at;
|
|
1273
|
+
let end = new BlockWidgetView(this.widget, len, this.deco);
|
|
1274
|
+
end.breakAfter = this.breakAfter;
|
|
1275
|
+
return end;
|
|
1276
|
+
}
|
|
1277
|
+
get children() { return noChildren; }
|
|
1278
|
+
sync(view) {
|
|
1279
|
+
if (!this.dom || !this.widget.updateDOM(this.dom, view)) {
|
|
1280
|
+
if (this.dom && this.prevWidget)
|
|
1281
|
+
this.prevWidget.destroy(this.dom);
|
|
1282
|
+
this.prevWidget = null;
|
|
1283
|
+
this.setDOM(this.widget.toDOM(view));
|
|
1284
|
+
this.dom.contentEditable = "false";
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
get overrideDOMText() {
|
|
1288
|
+
return this.parent ? this.parent.view.state.doc.slice(this.posAtStart, this.posAtEnd) : Text.empty;
|
|
1289
|
+
}
|
|
1290
|
+
domBoundsAround() { return null; }
|
|
1291
|
+
become(other) {
|
|
1292
|
+
if (other instanceof BlockWidgetView &&
|
|
1293
|
+
other.widget.constructor == this.widget.constructor) {
|
|
1294
|
+
if (!other.widget.compare(this.widget))
|
|
1295
|
+
this.markDirty(true);
|
|
1296
|
+
if (this.dom && !this.prevWidget)
|
|
1297
|
+
this.prevWidget = this.widget;
|
|
1298
|
+
this.widget = other.widget;
|
|
1299
|
+
this.length = other.length;
|
|
1300
|
+
this.deco = other.deco;
|
|
1301
|
+
this.breakAfter = other.breakAfter;
|
|
1302
|
+
return true;
|
|
1303
|
+
}
|
|
1304
|
+
return false;
|
|
1305
|
+
}
|
|
1306
|
+
ignoreMutation() { return true; }
|
|
1307
|
+
ignoreEvent(event) { return this.widget.ignoreEvent(event); }
|
|
1308
|
+
get isEditable() { return false; }
|
|
1309
|
+
get isWidget() { return true; }
|
|
1310
|
+
coordsAt(pos, side) {
|
|
1311
|
+
return this.widget.coordsAt(this.dom, pos, side);
|
|
1312
|
+
}
|
|
1313
|
+
destroy() {
|
|
1314
|
+
super.destroy();
|
|
1315
|
+
if (this.dom)
|
|
1316
|
+
this.widget.destroy(this.dom);
|
|
1317
|
+
}
|
|
1318
|
+
covers(side) {
|
|
1319
|
+
let { startSide, endSide } = this.deco;
|
|
1320
|
+
return startSide == endSide ? false : side < 0 ? startSide < 0 : endSide > 0;
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1094
1324
|
/**
|
|
1095
1325
|
Widgets added to the content are described by subclasses of this
|
|
1096
1326
|
class. Using a description object like that makes it possible to
|
|
@@ -1256,346 +1486,120 @@ class Decoration extends RangeValue {
|
|
|
1256
1486
|
startSide = (start ? (block ? -300000000 /* Side.BlockIncStart */ : -1 /* Side.InlineIncStart */) : 500000000 /* Side.NonIncStart */) - 1;
|
|
1257
1487
|
endSide = (end ? (block ? 200000000 /* Side.BlockIncEnd */ : 1 /* Side.InlineIncEnd */) : -600000000 /* Side.NonIncEnd */) + 1;
|
|
1258
1488
|
}
|
|
1259
|
-
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1260
|
-
}
|
|
1261
|
-
/**
|
|
1262
|
-
Create a line decoration, which can add DOM attributes to the
|
|
1263
|
-
line starting at the given position.
|
|
1264
|
-
*/
|
|
1265
|
-
static line(spec) {
|
|
1266
|
-
return new LineDecoration(spec);
|
|
1267
|
-
}
|
|
1268
|
-
/**
|
|
1269
|
-
Build a [`DecorationSet`](https://codemirror.net/6/docs/ref/#view.DecorationSet) from the given
|
|
1270
|
-
decorated range or ranges. If the ranges aren't already sorted,
|
|
1271
|
-
pass `true` for `sort` to make the library sort them for you.
|
|
1272
|
-
*/
|
|
1273
|
-
static set(of, sort = false) {
|
|
1274
|
-
return RangeSet.of(of, sort);
|
|
1275
|
-
}
|
|
1276
|
-
/**
|
|
1277
|
-
@internal
|
|
1278
|
-
*/
|
|
1279
|
-
hasHeight() { return this.widget ? this.widget.estimatedHeight > -1 : false; }
|
|
1280
|
-
}
|
|
1281
|
-
/**
|
|
1282
|
-
The empty set of decorations.
|
|
1283
|
-
*/
|
|
1284
|
-
Decoration.none = RangeSet.empty;
|
|
1285
|
-
class MarkDecoration extends Decoration {
|
|
1286
|
-
constructor(spec) {
|
|
1287
|
-
let { start, end } = getInclusive(spec);
|
|
1288
|
-
super(start ? -1 /* Side.InlineIncStart */ : 500000000 /* Side.NonIncStart */, end ? 1 /* Side.InlineIncEnd */ : -600000000 /* Side.NonIncEnd */, null, spec);
|
|
1289
|
-
this.tagName = spec.tagName || "span";
|
|
1290
|
-
this.class = spec.class || "";
|
|
1291
|
-
this.attrs = spec.attributes || null;
|
|
1292
|
-
}
|
|
1293
|
-
eq(other) {
|
|
1294
|
-
var _a, _b;
|
|
1295
|
-
return this == other ||
|
|
1296
|
-
other instanceof MarkDecoration &&
|
|
1297
|
-
this.tagName == other.tagName &&
|
|
1298
|
-
(this.class || ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a.class)) == (other.class || ((_b = other.attrs) === null || _b === void 0 ? void 0 : _b.class)) &&
|
|
1299
|
-
attrsEq(this.attrs, other.attrs, "class");
|
|
1300
|
-
}
|
|
1301
|
-
range(from, to = from) {
|
|
1302
|
-
if (from >= to)
|
|
1303
|
-
throw new RangeError("Mark decorations may not be empty");
|
|
1304
|
-
return super.range(from, to);
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
MarkDecoration.prototype.point = false;
|
|
1308
|
-
class LineDecoration extends Decoration {
|
|
1309
|
-
constructor(spec) {
|
|
1310
|
-
super(-200000000 /* Side.Line */, -200000000 /* Side.Line */, null, spec);
|
|
1311
|
-
}
|
|
1312
|
-
eq(other) {
|
|
1313
|
-
return other instanceof LineDecoration &&
|
|
1314
|
-
this.spec.class == other.spec.class &&
|
|
1315
|
-
attrsEq(this.spec.attributes, other.spec.attributes);
|
|
1316
|
-
}
|
|
1317
|
-
range(from, to = from) {
|
|
1318
|
-
if (to != from)
|
|
1319
|
-
throw new RangeError("Line decoration ranges must be zero-length");
|
|
1320
|
-
return super.range(from, to);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
LineDecoration.prototype.mapMode = MapMode.TrackBefore;
|
|
1324
|
-
LineDecoration.prototype.point = true;
|
|
1325
|
-
class PointDecoration extends Decoration {
|
|
1326
|
-
constructor(spec, startSide, endSide, block, widget, isReplace) {
|
|
1327
|
-
super(startSide, endSide, widget, spec);
|
|
1328
|
-
this.block = block;
|
|
1329
|
-
this.isReplace = isReplace;
|
|
1330
|
-
this.mapMode = !block ? MapMode.TrackDel : startSide <= 0 ? MapMode.TrackBefore : MapMode.TrackAfter;
|
|
1331
|
-
}
|
|
1332
|
-
// Only relevant when this.block == true
|
|
1333
|
-
get type() {
|
|
1334
|
-
return this.startSide < this.endSide ? BlockType.WidgetRange
|
|
1335
|
-
: this.startSide <= 0 ? BlockType.WidgetBefore : BlockType.WidgetAfter;
|
|
1336
|
-
}
|
|
1337
|
-
get heightRelevant() {
|
|
1338
|
-
return this.block || !!this.widget && (this.widget.estimatedHeight >= 5 || this.widget.lineBreaks > 0);
|
|
1339
|
-
}
|
|
1340
|
-
eq(other) {
|
|
1341
|
-
return other instanceof PointDecoration &&
|
|
1342
|
-
widgetsEq(this.widget, other.widget) &&
|
|
1343
|
-
this.block == other.block &&
|
|
1344
|
-
this.startSide == other.startSide && this.endSide == other.endSide;
|
|
1345
|
-
}
|
|
1346
|
-
range(from, to = from) {
|
|
1347
|
-
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide <= 0)))
|
|
1348
|
-
throw new RangeError("Invalid range for replacement decoration");
|
|
1349
|
-
if (!this.isReplace && to != from)
|
|
1350
|
-
throw new RangeError("Widget decorations can only have zero-length ranges");
|
|
1351
|
-
return super.range(from, to);
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
PointDecoration.prototype.point = true;
|
|
1355
|
-
function getInclusive(spec, block = false) {
|
|
1356
|
-
let { inclusiveStart: start, inclusiveEnd: end } = spec;
|
|
1357
|
-
if (start == null)
|
|
1358
|
-
start = spec.inclusive;
|
|
1359
|
-
if (end == null)
|
|
1360
|
-
end = spec.inclusive;
|
|
1361
|
-
return { start: start !== null && start !== void 0 ? start : block, end: end !== null && end !== void 0 ? end : block };
|
|
1362
|
-
}
|
|
1363
|
-
function widgetsEq(a, b) {
|
|
1364
|
-
return a == b || !!(a && b && a.compare(b));
|
|
1365
|
-
}
|
|
1366
|
-
function addRange(from, to, ranges, margin = 0) {
|
|
1367
|
-
let last = ranges.length - 1;
|
|
1368
|
-
if (last >= 0 && ranges[last] + margin >= from)
|
|
1369
|
-
ranges[last] = Math.max(ranges[last], to);
|
|
1370
|
-
else
|
|
1371
|
-
ranges.push(from, to);
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
class LineView extends ContentView {
|
|
1375
|
-
constructor() {
|
|
1376
|
-
super(...arguments);
|
|
1377
|
-
this.children = [];
|
|
1378
|
-
this.length = 0;
|
|
1379
|
-
this.prevAttrs = undefined;
|
|
1380
|
-
this.attrs = null;
|
|
1381
|
-
this.breakAfter = 0;
|
|
1382
|
-
}
|
|
1383
|
-
// Consumes source
|
|
1384
|
-
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
1385
|
-
if (source) {
|
|
1386
|
-
if (!(source instanceof LineView))
|
|
1387
|
-
return false;
|
|
1388
|
-
if (!this.dom)
|
|
1389
|
-
source.transferDOM(this); // Reuse source.dom when appropriate
|
|
1390
|
-
}
|
|
1391
|
-
if (hasStart)
|
|
1392
|
-
this.setDeco(source ? source.attrs : null);
|
|
1393
|
-
mergeChildrenInto(this, from, to, source ? source.children : [], openStart, openEnd);
|
|
1394
|
-
return true;
|
|
1395
|
-
}
|
|
1396
|
-
split(at) {
|
|
1397
|
-
let end = new LineView;
|
|
1398
|
-
end.breakAfter = this.breakAfter;
|
|
1399
|
-
if (this.length == 0)
|
|
1400
|
-
return end;
|
|
1401
|
-
let { i, off } = this.childPos(at);
|
|
1402
|
-
if (off) {
|
|
1403
|
-
end.append(this.children[i].split(off), 0);
|
|
1404
|
-
this.children[i].merge(off, this.children[i].length, null, false, 0, 0);
|
|
1405
|
-
i++;
|
|
1406
|
-
}
|
|
1407
|
-
for (let j = i; j < this.children.length; j++)
|
|
1408
|
-
end.append(this.children[j], 0);
|
|
1409
|
-
while (i > 0 && this.children[i - 1].length == 0)
|
|
1410
|
-
this.children[--i].destroy();
|
|
1411
|
-
this.children.length = i;
|
|
1412
|
-
this.markDirty();
|
|
1413
|
-
this.length = at;
|
|
1414
|
-
return end;
|
|
1415
|
-
}
|
|
1416
|
-
transferDOM(other) {
|
|
1417
|
-
if (!this.dom)
|
|
1418
|
-
return;
|
|
1419
|
-
this.markDirty();
|
|
1420
|
-
other.setDOM(this.dom);
|
|
1421
|
-
other.prevAttrs = this.prevAttrs === undefined ? this.attrs : this.prevAttrs;
|
|
1422
|
-
this.prevAttrs = undefined;
|
|
1423
|
-
this.dom = null;
|
|
1424
|
-
}
|
|
1425
|
-
setDeco(attrs) {
|
|
1426
|
-
if (!attrsEq(this.attrs, attrs)) {
|
|
1427
|
-
if (this.dom) {
|
|
1428
|
-
this.prevAttrs = this.attrs;
|
|
1429
|
-
this.markDirty();
|
|
1430
|
-
}
|
|
1431
|
-
this.attrs = attrs;
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
append(child, openStart) {
|
|
1435
|
-
joinInlineInto(this, child, openStart);
|
|
1436
|
-
}
|
|
1437
|
-
// Only called when building a line view in ContentBuilder
|
|
1438
|
-
addLineDeco(deco) {
|
|
1439
|
-
let attrs = deco.spec.attributes, cls = deco.spec.class;
|
|
1440
|
-
if (attrs)
|
|
1441
|
-
this.attrs = combineAttrs(attrs, this.attrs || {});
|
|
1442
|
-
if (cls)
|
|
1443
|
-
this.attrs = combineAttrs({ class: cls }, this.attrs || {});
|
|
1444
|
-
}
|
|
1445
|
-
domAtPos(pos) {
|
|
1446
|
-
return inlineDOMAtPos(this, pos);
|
|
1447
|
-
}
|
|
1448
|
-
reuseDOM(node) {
|
|
1449
|
-
if (node.nodeName == "DIV") {
|
|
1450
|
-
this.setDOM(node);
|
|
1451
|
-
this.flags |= 4 /* ViewFlag.AttrsDirty */ | 2 /* ViewFlag.NodeDirty */;
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
sync(view, track) {
|
|
1455
|
-
var _a;
|
|
1456
|
-
if (!this.dom) {
|
|
1457
|
-
this.setDOM(document.createElement("div"));
|
|
1458
|
-
this.dom.className = "cm-line";
|
|
1459
|
-
this.prevAttrs = this.attrs ? null : undefined;
|
|
1460
|
-
}
|
|
1461
|
-
else if (this.flags & 4 /* ViewFlag.AttrsDirty */) {
|
|
1462
|
-
clearAttributes(this.dom);
|
|
1463
|
-
this.dom.className = "cm-line";
|
|
1464
|
-
this.prevAttrs = this.attrs ? null : undefined;
|
|
1465
|
-
}
|
|
1466
|
-
if (this.prevAttrs !== undefined) {
|
|
1467
|
-
updateAttrs(this.dom, this.prevAttrs, this.attrs);
|
|
1468
|
-
this.dom.classList.add("cm-line");
|
|
1469
|
-
this.prevAttrs = undefined;
|
|
1470
|
-
}
|
|
1471
|
-
super.sync(view, track);
|
|
1472
|
-
let last = this.dom.lastChild;
|
|
1473
|
-
while (last && ContentView.get(last) instanceof MarkView)
|
|
1474
|
-
last = last.lastChild;
|
|
1475
|
-
if (!last || !this.length ||
|
|
1476
|
-
last.nodeName != "BR" && ((_a = ContentView.get(last)) === null || _a === void 0 ? void 0 : _a.isEditable) == false &&
|
|
1477
|
-
(!browser.ios || !this.children.some(ch => ch instanceof TextView))) {
|
|
1478
|
-
let hack = document.createElement("BR");
|
|
1479
|
-
hack.cmIgnore = true;
|
|
1480
|
-
this.dom.appendChild(hack);
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
measureTextSize() {
|
|
1484
|
-
if (this.children.length == 0 || this.length > 20)
|
|
1485
|
-
return null;
|
|
1486
|
-
let totalWidth = 0, textHeight;
|
|
1487
|
-
for (let child of this.children) {
|
|
1488
|
-
if (!(child instanceof TextView) || /[^ -~]/.test(child.text))
|
|
1489
|
-
return null;
|
|
1490
|
-
let rects = clientRectsFor(child.dom);
|
|
1491
|
-
if (rects.length != 1)
|
|
1492
|
-
return null;
|
|
1493
|
-
totalWidth += rects[0].width;
|
|
1494
|
-
textHeight = rects[0].height;
|
|
1495
|
-
}
|
|
1496
|
-
return !totalWidth ? null : {
|
|
1497
|
-
lineHeight: this.dom.getBoundingClientRect().height,
|
|
1498
|
-
charWidth: totalWidth / this.length,
|
|
1499
|
-
textHeight
|
|
1500
|
-
};
|
|
1501
|
-
}
|
|
1502
|
-
coordsAt(pos, side) {
|
|
1503
|
-
let rect = coordsInChildren(this, pos, side);
|
|
1504
|
-
// Correct rectangle height for empty lines when the returned
|
|
1505
|
-
// height is larger than the text height.
|
|
1506
|
-
if (!this.children.length && rect && this.parent) {
|
|
1507
|
-
let { heightOracle } = this.parent.view.viewState, height = rect.bottom - rect.top;
|
|
1508
|
-
if (Math.abs(height - heightOracle.lineHeight) < 2 && heightOracle.textHeight < height) {
|
|
1509
|
-
let dist = (height - heightOracle.textHeight) / 2;
|
|
1510
|
-
return { top: rect.top + dist, bottom: rect.bottom - dist, left: rect.left, right: rect.left };
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
return rect;
|
|
1489
|
+
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1514
1490
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
return
|
|
1491
|
+
/**
|
|
1492
|
+
Create a line decoration, which can add DOM attributes to the
|
|
1493
|
+
line starting at the given position.
|
|
1494
|
+
*/
|
|
1495
|
+
static line(spec) {
|
|
1496
|
+
return new LineDecoration(spec);
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
Build a [`DecorationSet`](https://codemirror.net/6/docs/ref/#view.DecorationSet) from the given
|
|
1500
|
+
decorated range or ranges. If the ranges aren't already sorted,
|
|
1501
|
+
pass `true` for `sort` to make the library sort them for you.
|
|
1502
|
+
*/
|
|
1503
|
+
static set(of, sort = false) {
|
|
1504
|
+
return RangeSet.of(of, sort);
|
|
1529
1505
|
}
|
|
1506
|
+
/**
|
|
1507
|
+
@internal
|
|
1508
|
+
*/
|
|
1509
|
+
hasHeight() { return this.widget ? this.widget.estimatedHeight > -1 : false; }
|
|
1530
1510
|
}
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1511
|
+
/**
|
|
1512
|
+
The empty set of decorations.
|
|
1513
|
+
*/
|
|
1514
|
+
Decoration.none = RangeSet.empty;
|
|
1515
|
+
class MarkDecoration extends Decoration {
|
|
1516
|
+
constructor(spec) {
|
|
1517
|
+
let { start, end } = getInclusive(spec);
|
|
1518
|
+
super(start ? -1 /* Side.InlineIncStart */ : 500000000 /* Side.NonIncStart */, end ? 1 /* Side.InlineIncEnd */ : -600000000 /* Side.NonIncEnd */, null, spec);
|
|
1519
|
+
this.tagName = spec.tagName || "span";
|
|
1520
|
+
this.class = spec.class || "";
|
|
1521
|
+
this.attrs = spec.attributes || null;
|
|
1539
1522
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1523
|
+
eq(other) {
|
|
1524
|
+
var _a, _b;
|
|
1525
|
+
return this == other ||
|
|
1526
|
+
other instanceof MarkDecoration &&
|
|
1527
|
+
this.tagName == other.tagName &&
|
|
1528
|
+
(this.class || ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a.class)) == (other.class || ((_b = other.attrs) === null || _b === void 0 ? void 0 : _b.class)) &&
|
|
1529
|
+
attrsEq(this.attrs, other.attrs, "class");
|
|
1546
1530
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1531
|
+
range(from, to = from) {
|
|
1532
|
+
if (from >= to)
|
|
1533
|
+
throw new RangeError("Mark decorations may not be empty");
|
|
1534
|
+
return super.range(from, to);
|
|
1549
1535
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
return end;
|
|
1536
|
+
}
|
|
1537
|
+
MarkDecoration.prototype.point = false;
|
|
1538
|
+
class LineDecoration extends Decoration {
|
|
1539
|
+
constructor(spec) {
|
|
1540
|
+
super(-200000000 /* Side.Line */, -200000000 /* Side.Line */, null, spec);
|
|
1556
1541
|
}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
this.prevWidget.destroy(this.dom);
|
|
1562
|
-
this.prevWidget = null;
|
|
1563
|
-
this.setDOM(this.widget.toDOM(view));
|
|
1564
|
-
this.dom.contentEditable = "false";
|
|
1565
|
-
}
|
|
1542
|
+
eq(other) {
|
|
1543
|
+
return other instanceof LineDecoration &&
|
|
1544
|
+
this.spec.class == other.spec.class &&
|
|
1545
|
+
attrsEq(this.spec.attributes, other.spec.attributes);
|
|
1566
1546
|
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1547
|
+
range(from, to = from) {
|
|
1548
|
+
if (to != from)
|
|
1549
|
+
throw new RangeError("Line decoration ranges must be zero-length");
|
|
1550
|
+
return super.range(from, to);
|
|
1569
1551
|
}
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
this.length = other.length;
|
|
1580
|
-
this.type = other.type;
|
|
1581
|
-
this.breakAfter = other.breakAfter;
|
|
1582
|
-
return true;
|
|
1583
|
-
}
|
|
1584
|
-
return false;
|
|
1552
|
+
}
|
|
1553
|
+
LineDecoration.prototype.mapMode = MapMode.TrackBefore;
|
|
1554
|
+
LineDecoration.prototype.point = true;
|
|
1555
|
+
class PointDecoration extends Decoration {
|
|
1556
|
+
constructor(spec, startSide, endSide, block, widget, isReplace) {
|
|
1557
|
+
super(startSide, endSide, widget, spec);
|
|
1558
|
+
this.block = block;
|
|
1559
|
+
this.isReplace = isReplace;
|
|
1560
|
+
this.mapMode = !block ? MapMode.TrackDel : startSide <= 0 ? MapMode.TrackBefore : MapMode.TrackAfter;
|
|
1585
1561
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
coordsAt(pos, side) {
|
|
1591
|
-
return this.widget.coordsAt(this.dom, pos, side);
|
|
1562
|
+
// Only relevant when this.block == true
|
|
1563
|
+
get type() {
|
|
1564
|
+
return this.startSide != this.endSide ? BlockType.WidgetRange
|
|
1565
|
+
: this.startSide <= 0 ? BlockType.WidgetBefore : BlockType.WidgetAfter;
|
|
1592
1566
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1567
|
+
get heightRelevant() {
|
|
1568
|
+
return this.block || !!this.widget && (this.widget.estimatedHeight >= 5 || this.widget.lineBreaks > 0);
|
|
1569
|
+
}
|
|
1570
|
+
eq(other) {
|
|
1571
|
+
return other instanceof PointDecoration &&
|
|
1572
|
+
widgetsEq(this.widget, other.widget) &&
|
|
1573
|
+
this.block == other.block &&
|
|
1574
|
+
this.startSide == other.startSide && this.endSide == other.endSide;
|
|
1575
|
+
}
|
|
1576
|
+
range(from, to = from) {
|
|
1577
|
+
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide <= 0)))
|
|
1578
|
+
throw new RangeError("Invalid range for replacement decoration");
|
|
1579
|
+
if (!this.isReplace && to != from)
|
|
1580
|
+
throw new RangeError("Widget decorations can only have zero-length ranges");
|
|
1581
|
+
return super.range(from, to);
|
|
1597
1582
|
}
|
|
1598
1583
|
}
|
|
1584
|
+
PointDecoration.prototype.point = true;
|
|
1585
|
+
function getInclusive(spec, block = false) {
|
|
1586
|
+
let { inclusiveStart: start, inclusiveEnd: end } = spec;
|
|
1587
|
+
if (start == null)
|
|
1588
|
+
start = spec.inclusive;
|
|
1589
|
+
if (end == null)
|
|
1590
|
+
end = spec.inclusive;
|
|
1591
|
+
return { start: start !== null && start !== void 0 ? start : block, end: end !== null && end !== void 0 ? end : block };
|
|
1592
|
+
}
|
|
1593
|
+
function widgetsEq(a, b) {
|
|
1594
|
+
return a == b || !!(a && b && a.compare(b));
|
|
1595
|
+
}
|
|
1596
|
+
function addRange(from, to, ranges, margin = 0) {
|
|
1597
|
+
let last = ranges.length - 1;
|
|
1598
|
+
if (last >= 0 && ranges[last] + margin >= from)
|
|
1599
|
+
ranges[last] = Math.max(ranges[last], to);
|
|
1600
|
+
else
|
|
1601
|
+
ranges.push(from, to);
|
|
1602
|
+
}
|
|
1599
1603
|
|
|
1600
1604
|
class ContentBuilder {
|
|
1601
1605
|
constructor(doc, pos, end, disallowBlockEffectsFor) {
|
|
@@ -1621,7 +1625,7 @@ class ContentBuilder {
|
|
|
1621
1625
|
if (this.content.length == 0)
|
|
1622
1626
|
return !this.breakAtStart && this.doc.lineAt(this.pos).from != this.pos;
|
|
1623
1627
|
let last = this.content[this.content.length - 1];
|
|
1624
|
-
return !last.breakAfter
|
|
1628
|
+
return !(last.breakAfter || last instanceof BlockWidgetView && last.deco.endSide < 0);
|
|
1625
1629
|
}
|
|
1626
1630
|
getLine() {
|
|
1627
1631
|
if (!this.curLine) {
|
|
@@ -1646,7 +1650,7 @@ class ContentBuilder {
|
|
|
1646
1650
|
this.flushBuffer();
|
|
1647
1651
|
else
|
|
1648
1652
|
this.pendingBuffer = 0 /* Buf.No */;
|
|
1649
|
-
if (!this.posCovered())
|
|
1653
|
+
if (!openEnd && !this.posCovered())
|
|
1650
1654
|
this.getLine();
|
|
1651
1655
|
}
|
|
1652
1656
|
buildText(length, active, openStart) {
|
|
@@ -1699,10 +1703,9 @@ class ContentBuilder {
|
|
|
1699
1703
|
let len = to - from;
|
|
1700
1704
|
if (deco instanceof PointDecoration) {
|
|
1701
1705
|
if (deco.block) {
|
|
1702
|
-
|
|
1703
|
-
if (type == BlockType.WidgetAfter && !this.posCovered())
|
|
1706
|
+
if (deco.startSide > 0 && !this.posCovered())
|
|
1704
1707
|
this.getLine();
|
|
1705
|
-
this.addBlockWidget(new BlockWidgetView(deco.widget || new NullWidget("div"), len,
|
|
1708
|
+
this.addBlockWidget(new BlockWidgetView(deco.widget || new NullWidget("div"), len, deco));
|
|
1706
1709
|
}
|
|
1707
1710
|
else {
|
|
1708
1711
|
let view = WidgetView.create(deco.widget || new NullWidget("span"), len, len ? 0 : deco.startSide);
|
|
@@ -1837,10 +1840,15 @@ class ViewPlugin {
|
|
|
1837
1840
|
/**
|
|
1838
1841
|
@internal
|
|
1839
1842
|
*/
|
|
1840
|
-
domEventHandlers,
|
|
1843
|
+
domEventHandlers,
|
|
1844
|
+
/**
|
|
1845
|
+
@internal
|
|
1846
|
+
*/
|
|
1847
|
+
domEventObservers, buildExtensions) {
|
|
1841
1848
|
this.id = id;
|
|
1842
1849
|
this.create = create;
|
|
1843
1850
|
this.domEventHandlers = domEventHandlers;
|
|
1851
|
+
this.domEventObservers = domEventObservers;
|
|
1844
1852
|
this.extension = buildExtensions(this);
|
|
1845
1853
|
}
|
|
1846
1854
|
/**
|
|
@@ -1848,8 +1856,8 @@ class ViewPlugin {
|
|
|
1848
1856
|
plugin's value, given an editor view.
|
|
1849
1857
|
*/
|
|
1850
1858
|
static define(create, spec) {
|
|
1851
|
-
const { eventHandlers, provide, decorations: deco } = spec || {};
|
|
1852
|
-
return new ViewPlugin(nextPluginID++, create, eventHandlers, plugin => {
|
|
1859
|
+
const { eventHandlers, eventObservers, provide, decorations: deco } = spec || {};
|
|
1860
|
+
return new ViewPlugin(nextPluginID++, create, eventHandlers, eventObservers, plugin => {
|
|
1853
1861
|
let ext = [viewPlugin.of(plugin)];
|
|
1854
1862
|
if (deco)
|
|
1855
1863
|
ext.push(decorations.of(view => {
|
|
@@ -2934,15 +2942,19 @@ class DocView extends ContentView {
|
|
|
2934
2942
|
return this.children[i].domAtPos(off);
|
|
2935
2943
|
}
|
|
2936
2944
|
coordsAt(pos, side) {
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2945
|
+
let best = null, bestPos = 0;
|
|
2946
|
+
for (let off = this.length, i = this.children.length - 1; i >= 0; i--) {
|
|
2947
|
+
let child = this.children[i], end = off - child.breakAfter, start = end - child.length;
|
|
2948
|
+
if (end < pos)
|
|
2949
|
+
break;
|
|
2950
|
+
if (start <= pos && (start < pos || child.covers(-1)) && (end > pos || child.covers(1)) &&
|
|
2951
|
+
(!best || child instanceof LineView && !(best instanceof LineView && side >= 0))) {
|
|
2952
|
+
best = child;
|
|
2953
|
+
bestPos = start;
|
|
2954
|
+
}
|
|
2944
2955
|
off = start;
|
|
2945
2956
|
}
|
|
2957
|
+
return best ? best.coordsAt(pos - bestPos, side) : null;
|
|
2946
2958
|
}
|
|
2947
2959
|
coordsForChar(pos) {
|
|
2948
2960
|
let { i, off } = this.childPos(pos, 1), child = this.children[i];
|
|
@@ -3528,7 +3540,7 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3528
3540
|
return EditorSelection.cursor(startPos, start.assoc);
|
|
3529
3541
|
let goal = start.goalColumn, startY;
|
|
3530
3542
|
let rect = view.contentDOM.getBoundingClientRect();
|
|
3531
|
-
let startCoords = view.coordsAtPos(startPos), docTop = view.documentTop;
|
|
3543
|
+
let startCoords = view.coordsAtPos(startPos, start.assoc || -1), docTop = view.documentTop;
|
|
3532
3544
|
if (startCoords) {
|
|
3533
3545
|
if (goal == null)
|
|
3534
3546
|
goal = startCoords.left - rect.left;
|
|
@@ -3545,8 +3557,11 @@ function moveVertically(view, start, forward, distance) {
|
|
|
3545
3557
|
for (let extra = 0;; extra += 10) {
|
|
3546
3558
|
let curY = startY + (dist + extra) * dir;
|
|
3547
3559
|
let pos = posAtCoords(view, { x: resolvedGoal, y: curY }, false, dir);
|
|
3548
|
-
if (curY < rect.top || curY > rect.bottom || (dir < 0 ? pos < startPos : pos > startPos))
|
|
3549
|
-
|
|
3560
|
+
if (curY < rect.top || curY > rect.bottom || (dir < 0 ? pos < startPos : pos > startPos)) {
|
|
3561
|
+
let charRect = view.docView.coordsForChar(pos);
|
|
3562
|
+
let assoc = !charRect || curY < charRect.top ? -1 : 1;
|
|
3563
|
+
return EditorSelection.cursor(pos, assoc, undefined, goal);
|
|
3564
|
+
}
|
|
3550
3565
|
}
|
|
3551
3566
|
}
|
|
3552
3567
|
function skipAtomicRanges(atoms, pos, bias) {
|
|
@@ -3577,13 +3592,13 @@ class InputState {
|
|
|
3577
3592
|
this.lastSelectionTime = Date.now();
|
|
3578
3593
|
}
|
|
3579
3594
|
constructor(view) {
|
|
3595
|
+
this.view = view;
|
|
3580
3596
|
this.lastKeyCode = 0;
|
|
3581
3597
|
this.lastKeyTime = 0;
|
|
3582
3598
|
this.lastTouchTime = 0;
|
|
3583
3599
|
this.lastFocusTime = 0;
|
|
3584
3600
|
this.lastScrollTop = 0;
|
|
3585
3601
|
this.lastScrollLeft = 0;
|
|
3586
|
-
this.chromeScrollHack = -1;
|
|
3587
3602
|
// On iOS, some keys need to have their default behavior happen
|
|
3588
3603
|
// (after which we retroactively handle them and reset the DOM) to
|
|
3589
3604
|
// avoid messing up the virtual keyboard state.
|
|
@@ -3593,8 +3608,7 @@ class InputState {
|
|
|
3593
3608
|
this.lastEscPress = 0;
|
|
3594
3609
|
this.lastContextMenu = 0;
|
|
3595
3610
|
this.scrollHandlers = [];
|
|
3596
|
-
this.
|
|
3597
|
-
this.customHandlers = [];
|
|
3611
|
+
this.handlers = Object.create(null);
|
|
3598
3612
|
// -1 means not in a composition. Otherwise, this counts the number
|
|
3599
3613
|
// of changes made during the composition. The count is used to
|
|
3600
3614
|
// avoid treating the start state of the composition, before any
|
|
@@ -3615,29 +3629,10 @@ class InputState {
|
|
|
3615
3629
|
// the mutation events fire shortly after the compositionend event
|
|
3616
3630
|
this.compositionPendingChange = false;
|
|
3617
3631
|
this.mouseSelection = null;
|
|
3618
|
-
|
|
3619
|
-
if (this.ignoreDuringComposition(event))
|
|
3620
|
-
return;
|
|
3621
|
-
if (event.type == "keydown" && this.keydown(view, event))
|
|
3622
|
-
return;
|
|
3623
|
-
if (this.mustFlushObserver(event))
|
|
3624
|
-
view.observer.forceFlush();
|
|
3625
|
-
if (this.runCustomHandlers(event.type, view, event))
|
|
3626
|
-
event.preventDefault();
|
|
3627
|
-
else
|
|
3628
|
-
handler(view, event);
|
|
3629
|
-
};
|
|
3630
|
-
for (let type in handlers) {
|
|
3631
|
-
let handler = handlers[type];
|
|
3632
|
-
view.contentDOM.addEventListener(type, event => {
|
|
3633
|
-
if (eventBelongsToEditor(view, event))
|
|
3634
|
-
handleEvent(handler, event);
|
|
3635
|
-
}, handlerOptions[type]);
|
|
3636
|
-
this.registeredEvents.push(type);
|
|
3637
|
-
}
|
|
3632
|
+
this.handleEvent = this.handleEvent.bind(this);
|
|
3638
3633
|
view.scrollDOM.addEventListener("mousedown", (event) => {
|
|
3639
3634
|
if (event.target == view.scrollDOM && event.clientY > view.contentDOM.getBoundingClientRect().bottom) {
|
|
3640
|
-
|
|
3635
|
+
this.runHandlers("mousedown", event);
|
|
3641
3636
|
if (!event.defaultPrevented && event.button == 2) {
|
|
3642
3637
|
// Make sure the content covers the entire scroller height, in order
|
|
3643
3638
|
// to catch a native context menu click below it
|
|
@@ -3649,23 +3644,8 @@ class InputState {
|
|
|
3649
3644
|
});
|
|
3650
3645
|
view.scrollDOM.addEventListener("drop", (event) => {
|
|
3651
3646
|
if (event.target == view.scrollDOM && event.clientY > view.contentDOM.getBoundingClientRect().bottom)
|
|
3652
|
-
|
|
3647
|
+
this.runHandlers("drop", event);
|
|
3653
3648
|
});
|
|
3654
|
-
if (browser.chrome && browser.chrome_version == 102) { // FIXME remove at some point
|
|
3655
|
-
// On Chrome 102, viewport updates somehow stop wheel-based
|
|
3656
|
-
// scrolling. Turning off pointer events during the scroll seems
|
|
3657
|
-
// to avoid the issue.
|
|
3658
|
-
view.scrollDOM.addEventListener("wheel", () => {
|
|
3659
|
-
if (this.chromeScrollHack < 0)
|
|
3660
|
-
view.contentDOM.style.pointerEvents = "none";
|
|
3661
|
-
else
|
|
3662
|
-
window.clearTimeout(this.chromeScrollHack);
|
|
3663
|
-
this.chromeScrollHack = setTimeout(() => {
|
|
3664
|
-
this.chromeScrollHack = -1;
|
|
3665
|
-
view.contentDOM.style.pointerEvents = "";
|
|
3666
|
-
}, 100);
|
|
3667
|
-
}, { passive: true });
|
|
3668
|
-
}
|
|
3669
3649
|
this.notifiedFocused = view.hasFocus;
|
|
3670
3650
|
// On Safari adding an input event handler somehow prevents an
|
|
3671
3651
|
// issue where the composition vanishes when you press enter.
|
|
@@ -3674,63 +3654,54 @@ class InputState {
|
|
|
3674
3654
|
if (browser.gecko)
|
|
3675
3655
|
firefoxCopyCutHack(view.contentDOM.ownerDocument);
|
|
3676
3656
|
}
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
}
|
|
3696
|
-
runCustomHandlers(type, view, event) {
|
|
3697
|
-
for (let set of this.customHandlers) {
|
|
3698
|
-
let handler = set.handlers[type];
|
|
3699
|
-
if (handler) {
|
|
3700
|
-
try {
|
|
3701
|
-
if (handler.call(set.plugin, event, view) || event.defaultPrevented)
|
|
3702
|
-
return true;
|
|
3703
|
-
}
|
|
3704
|
-
catch (e) {
|
|
3705
|
-
logException(view.state, e);
|
|
3657
|
+
handleEvent(event) {
|
|
3658
|
+
if (!eventBelongsToEditor(this.view, event) || this.ignoreDuringComposition(event))
|
|
3659
|
+
return;
|
|
3660
|
+
if (event.type == "keydown" && this.keydown(event))
|
|
3661
|
+
return;
|
|
3662
|
+
this.runHandlers(event.type, event);
|
|
3663
|
+
}
|
|
3664
|
+
runHandlers(type, event) {
|
|
3665
|
+
let handlers = this.handlers[type];
|
|
3666
|
+
if (handlers) {
|
|
3667
|
+
for (let observer of handlers.observers)
|
|
3668
|
+
observer(this.view, event);
|
|
3669
|
+
for (let handler of handlers.handlers) {
|
|
3670
|
+
if (event.defaultPrevented)
|
|
3671
|
+
break;
|
|
3672
|
+
if (handler(this.view, event)) {
|
|
3673
|
+
event.preventDefault();
|
|
3674
|
+
break;
|
|
3706
3675
|
}
|
|
3707
3676
|
}
|
|
3708
3677
|
}
|
|
3709
|
-
return false;
|
|
3710
3678
|
}
|
|
3711
|
-
|
|
3712
|
-
this.
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
catch (e) {
|
|
3721
|
-
logException(view.state, e);
|
|
3679
|
+
ensureHandlers(plugins) {
|
|
3680
|
+
let handlers = computeHandlers(plugins), prev = this.handlers, dom = this.view.contentDOM;
|
|
3681
|
+
for (let type in handlers)
|
|
3682
|
+
if (type != "scroll") {
|
|
3683
|
+
let passive = !handlers[type].handlers.length;
|
|
3684
|
+
let exists = prev[type];
|
|
3685
|
+
if (exists && passive != !exists.handlers.length) {
|
|
3686
|
+
dom.removeEventListener(type, this.handleEvent);
|
|
3687
|
+
exists = null;
|
|
3722
3688
|
}
|
|
3689
|
+
if (!exists)
|
|
3690
|
+
dom.addEventListener(type, this.handleEvent, { passive });
|
|
3723
3691
|
}
|
|
3724
|
-
|
|
3692
|
+
for (let type in prev)
|
|
3693
|
+
if (type != "scroll" && !handlers[type])
|
|
3694
|
+
dom.removeEventListener(type, this.handleEvent);
|
|
3695
|
+
this.handlers = handlers;
|
|
3725
3696
|
}
|
|
3726
|
-
keydown(
|
|
3697
|
+
keydown(event) {
|
|
3727
3698
|
// Must always run, even if a custom handler handled the event
|
|
3728
3699
|
this.lastKeyCode = event.keyCode;
|
|
3729
3700
|
this.lastKeyTime = Date.now();
|
|
3730
3701
|
if (event.keyCode == 9 && Date.now() < this.lastEscPress + 2000)
|
|
3731
3702
|
return true;
|
|
3732
3703
|
if (event.keyCode != 27 && modifierCodes.indexOf(event.keyCode) < 0)
|
|
3733
|
-
view.inputState.lastEscPress = 0;
|
|
3704
|
+
this.view.inputState.lastEscPress = 0;
|
|
3734
3705
|
// Chrome for Android usually doesn't fire proper key events, but
|
|
3735
3706
|
// occasionally does, usually surrounded by a bunch of complicated
|
|
3736
3707
|
// composition changes. When an enter or backspace key event is
|
|
@@ -3738,10 +3709,10 @@ class InputState {
|
|
|
3738
3709
|
// dispatch it.
|
|
3739
3710
|
if (browser.android && browser.chrome && !event.synthetic &&
|
|
3740
3711
|
(event.keyCode == 13 || event.keyCode == 8)) {
|
|
3741
|
-
view.observer.delayAndroidKey(event.key, event.keyCode);
|
|
3712
|
+
this.view.observer.delayAndroidKey(event.key, event.keyCode);
|
|
3742
3713
|
return true;
|
|
3743
3714
|
}
|
|
3744
|
-
//
|
|
3715
|
+
// Preventing the default behavior of Enter on iOS makes the
|
|
3745
3716
|
// virtual keyboard get stuck in the wrong (lowercase)
|
|
3746
3717
|
// state. So we let it go through, and then, in
|
|
3747
3718
|
// applyDOMChange, notify key handlers of it and reset to
|
|
@@ -3751,17 +3722,19 @@ class InputState {
|
|
|
3751
3722
|
((pending = PendingKeys.find(key => key.keyCode == event.keyCode)) && !event.ctrlKey ||
|
|
3752
3723
|
EmacsyPendingKeys.indexOf(event.key) > -1 && event.ctrlKey && !event.shiftKey)) {
|
|
3753
3724
|
this.pendingIOSKey = pending || event;
|
|
3754
|
-
setTimeout(() => this.flushIOSKey(
|
|
3725
|
+
setTimeout(() => this.flushIOSKey(), 250);
|
|
3755
3726
|
return true;
|
|
3756
3727
|
}
|
|
3728
|
+
if (event.keyCode != 229)
|
|
3729
|
+
this.view.observer.forceFlush();
|
|
3757
3730
|
return false;
|
|
3758
3731
|
}
|
|
3759
|
-
flushIOSKey(
|
|
3732
|
+
flushIOSKey() {
|
|
3760
3733
|
let key = this.pendingIOSKey;
|
|
3761
3734
|
if (!key)
|
|
3762
3735
|
return false;
|
|
3763
3736
|
this.pendingIOSKey = undefined;
|
|
3764
|
-
return dispatchKey(view.contentDOM, key.key, key.keyCode);
|
|
3737
|
+
return dispatchKey(this.view.contentDOM, key.key, key.keyCode);
|
|
3765
3738
|
}
|
|
3766
3739
|
ignoreDuringComposition(event) {
|
|
3767
3740
|
if (!/^key/.test(event.type))
|
|
@@ -3780,9 +3753,6 @@ class InputState {
|
|
|
3780
3753
|
}
|
|
3781
3754
|
return false;
|
|
3782
3755
|
}
|
|
3783
|
-
mustFlushObserver(event) {
|
|
3784
|
-
return event.type == "keydown" && event.keyCode != 229;
|
|
3785
|
-
}
|
|
3786
3756
|
startMouseSelection(mouseSelection) {
|
|
3787
3757
|
if (this.mouseSelection)
|
|
3788
3758
|
this.mouseSelection.destroy();
|
|
@@ -3799,6 +3769,42 @@ class InputState {
|
|
|
3799
3769
|
this.mouseSelection.destroy();
|
|
3800
3770
|
}
|
|
3801
3771
|
}
|
|
3772
|
+
function bindHandler(plugin, handler) {
|
|
3773
|
+
return (view, event) => {
|
|
3774
|
+
try {
|
|
3775
|
+
return handler.call(plugin, event, view);
|
|
3776
|
+
}
|
|
3777
|
+
catch (e) {
|
|
3778
|
+
logException(view.state, e);
|
|
3779
|
+
}
|
|
3780
|
+
};
|
|
3781
|
+
}
|
|
3782
|
+
function computeHandlers(plugins) {
|
|
3783
|
+
let result = Object.create(null);
|
|
3784
|
+
function record(type) {
|
|
3785
|
+
return result[type] || (result[type] = { observers: [], handlers: [] });
|
|
3786
|
+
}
|
|
3787
|
+
for (let plugin of plugins) {
|
|
3788
|
+
let spec = plugin.spec;
|
|
3789
|
+
if (spec && spec.domEventHandlers)
|
|
3790
|
+
for (let type in spec.domEventHandlers) {
|
|
3791
|
+
let f = spec.domEventHandlers[type];
|
|
3792
|
+
if (f)
|
|
3793
|
+
record(type).handlers.push(bindHandler(plugin.value, f));
|
|
3794
|
+
}
|
|
3795
|
+
if (spec && spec.domEventObservers)
|
|
3796
|
+
for (let type in spec.domEventObservers) {
|
|
3797
|
+
let f = spec.domEventObservers[type];
|
|
3798
|
+
if (f)
|
|
3799
|
+
record(type).observers.push(bindHandler(plugin.value, f));
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3802
|
+
for (let type in handlers)
|
|
3803
|
+
record(type).handlers.push(handlers[type]);
|
|
3804
|
+
for (let type in observers)
|
|
3805
|
+
record(type).observers.push(observers[type]);
|
|
3806
|
+
return result;
|
|
3807
|
+
}
|
|
3802
3808
|
const PendingKeys = [
|
|
3803
3809
|
{ key: "Backspace", keyCode: 8, inputType: "deleteContentBackward" },
|
|
3804
3810
|
{ key: "Enter", keyCode: 13, inputType: "insertParagraph" },
|
|
@@ -3836,10 +3842,8 @@ class MouseSelection {
|
|
|
3836
3842
|
start(event) {
|
|
3837
3843
|
// When clicking outside of the selection, immediately apply the
|
|
3838
3844
|
// effect of starting the selection
|
|
3839
|
-
if (this.dragging === false)
|
|
3840
|
-
event.preventDefault();
|
|
3845
|
+
if (this.dragging === false)
|
|
3841
3846
|
this.select(event);
|
|
3842
|
-
}
|
|
3843
3847
|
}
|
|
3844
3848
|
move(event) {
|
|
3845
3849
|
var _a;
|
|
@@ -3975,7 +3979,7 @@ function eventBelongsToEditor(view, event) {
|
|
|
3975
3979
|
return true;
|
|
3976
3980
|
}
|
|
3977
3981
|
const handlers = /*@__PURE__*/Object.create(null);
|
|
3978
|
-
const
|
|
3982
|
+
const observers = /*@__PURE__*/Object.create(null);
|
|
3979
3983
|
// This is very crude, but unfortunately both these browsers _pretend_
|
|
3980
3984
|
// that they have a clipboard API—all the objects and methods are
|
|
3981
3985
|
// there, they just don't work, and they are hard to test.
|
|
@@ -4025,23 +4029,27 @@ function doPaste(view, input) {
|
|
|
4025
4029
|
scrollIntoView: true
|
|
4026
4030
|
});
|
|
4027
4031
|
}
|
|
4032
|
+
observers.scroll = view => {
|
|
4033
|
+
view.inputState.lastScrollTop = view.scrollDOM.scrollTop;
|
|
4034
|
+
view.inputState.lastScrollLeft = view.scrollDOM.scrollLeft;
|
|
4035
|
+
};
|
|
4028
4036
|
handlers.keydown = (view, event) => {
|
|
4029
4037
|
view.inputState.setSelectionOrigin("select");
|
|
4030
4038
|
if (event.keyCode == 27)
|
|
4031
4039
|
view.inputState.lastEscPress = Date.now();
|
|
4040
|
+
return false;
|
|
4032
4041
|
};
|
|
4033
|
-
|
|
4042
|
+
observers.touchstart = (view, e) => {
|
|
4034
4043
|
view.inputState.lastTouchTime = Date.now();
|
|
4035
4044
|
view.inputState.setSelectionOrigin("select.pointer");
|
|
4036
4045
|
};
|
|
4037
|
-
|
|
4046
|
+
observers.touchmove = view => {
|
|
4038
4047
|
view.inputState.setSelectionOrigin("select.pointer");
|
|
4039
4048
|
};
|
|
4040
|
-
handlerOptions.touchstart = handlerOptions.touchmove = { passive: true };
|
|
4041
4049
|
handlers.mousedown = (view, event) => {
|
|
4042
4050
|
view.observer.flush();
|
|
4043
4051
|
if (view.inputState.lastTouchTime > Date.now() - 2000)
|
|
4044
|
-
return; // Ignore touch interaction
|
|
4052
|
+
return false; // Ignore touch interaction
|
|
4045
4053
|
let style = null;
|
|
4046
4054
|
for (let makeStyle of view.state.facet(mouseSelectionStyle)) {
|
|
4047
4055
|
style = makeStyle(view, event);
|
|
@@ -4055,9 +4063,13 @@ handlers.mousedown = (view, event) => {
|
|
|
4055
4063
|
view.inputState.startMouseSelection(new MouseSelection(view, event, style, mustFocus));
|
|
4056
4064
|
if (mustFocus)
|
|
4057
4065
|
view.observer.ignore(() => focusPreventScroll(view.contentDOM));
|
|
4058
|
-
|
|
4059
|
-
|
|
4066
|
+
let mouseSel = view.inputState.mouseSelection;
|
|
4067
|
+
if (mouseSel) {
|
|
4068
|
+
mouseSel.start(event);
|
|
4069
|
+
return !mouseSel.dragging;
|
|
4070
|
+
}
|
|
4060
4071
|
}
|
|
4072
|
+
return false;
|
|
4061
4073
|
};
|
|
4062
4074
|
function rangeForClick(view, pos, bias, type) {
|
|
4063
4075
|
if (type == 1) { // Single click
|
|
@@ -4161,12 +4173,12 @@ handlers.dragstart = (view, event) => {
|
|
|
4161
4173
|
event.dataTransfer.setData("Text", view.state.sliceDoc(main.from, main.to));
|
|
4162
4174
|
event.dataTransfer.effectAllowed = "copyMove";
|
|
4163
4175
|
}
|
|
4176
|
+
return false;
|
|
4164
4177
|
};
|
|
4165
4178
|
function dropText(view, event, text, direct) {
|
|
4166
4179
|
if (!text)
|
|
4167
4180
|
return;
|
|
4168
4181
|
let dropPos = view.posAtCoords({ x: event.clientX, y: event.clientY }, false);
|
|
4169
|
-
event.preventDefault();
|
|
4170
4182
|
let { mouseSelection } = view.inputState;
|
|
4171
4183
|
let del = direct && mouseSelection && mouseSelection.dragging && dragMovesSelection(view, event) ?
|
|
4172
4184
|
{ from: mouseSelection.dragging.from, to: mouseSelection.dragging.to } : null;
|
|
@@ -4181,12 +4193,11 @@ function dropText(view, event, text, direct) {
|
|
|
4181
4193
|
}
|
|
4182
4194
|
handlers.drop = (view, event) => {
|
|
4183
4195
|
if (!event.dataTransfer)
|
|
4184
|
-
return;
|
|
4196
|
+
return false;
|
|
4185
4197
|
if (view.state.readOnly)
|
|
4186
|
-
return
|
|
4198
|
+
return true;
|
|
4187
4199
|
let files = event.dataTransfer.files;
|
|
4188
4200
|
if (files && files.length) { // For a file drop, read the file's text.
|
|
4189
|
-
event.preventDefault();
|
|
4190
4201
|
let text = Array(files.length), read = 0;
|
|
4191
4202
|
let finishFile = () => {
|
|
4192
4203
|
if (++read == files.length)
|
|
@@ -4202,22 +4213,29 @@ handlers.drop = (view, event) => {
|
|
|
4202
4213
|
};
|
|
4203
4214
|
reader.readAsText(files[i]);
|
|
4204
4215
|
}
|
|
4216
|
+
return true;
|
|
4205
4217
|
}
|
|
4206
4218
|
else {
|
|
4207
|
-
|
|
4219
|
+
let text = event.dataTransfer.getData("Text");
|
|
4220
|
+
if (text) {
|
|
4221
|
+
dropText(view, event, text, true);
|
|
4222
|
+
return true;
|
|
4223
|
+
}
|
|
4208
4224
|
}
|
|
4225
|
+
return false;
|
|
4209
4226
|
};
|
|
4210
4227
|
handlers.paste = (view, event) => {
|
|
4211
4228
|
if (view.state.readOnly)
|
|
4212
|
-
return
|
|
4229
|
+
return true;
|
|
4213
4230
|
view.observer.flush();
|
|
4214
4231
|
let data = brokenClipboardAPI ? null : event.clipboardData;
|
|
4215
4232
|
if (data) {
|
|
4216
4233
|
doPaste(view, data.getData("text/plain") || data.getData("text/uri-text"));
|
|
4217
|
-
|
|
4234
|
+
return true;
|
|
4218
4235
|
}
|
|
4219
4236
|
else {
|
|
4220
4237
|
capturePaste(view);
|
|
4238
|
+
return false;
|
|
4221
4239
|
}
|
|
4222
4240
|
};
|
|
4223
4241
|
function captureCopy(view, text) {
|
|
@@ -4263,23 +4281,24 @@ let lastLinewiseCopy = null;
|
|
|
4263
4281
|
handlers.copy = handlers.cut = (view, event) => {
|
|
4264
4282
|
let { text, ranges, linewise } = copiedRange(view.state);
|
|
4265
4283
|
if (!text && !linewise)
|
|
4266
|
-
return;
|
|
4284
|
+
return false;
|
|
4267
4285
|
lastLinewiseCopy = linewise ? text : null;
|
|
4286
|
+
if (event.type == "cut" && !view.state.readOnly)
|
|
4287
|
+
view.dispatch({
|
|
4288
|
+
changes: ranges,
|
|
4289
|
+
scrollIntoView: true,
|
|
4290
|
+
userEvent: "delete.cut"
|
|
4291
|
+
});
|
|
4268
4292
|
let data = brokenClipboardAPI ? null : event.clipboardData;
|
|
4269
4293
|
if (data) {
|
|
4270
|
-
event.preventDefault();
|
|
4271
4294
|
data.clearData();
|
|
4272
4295
|
data.setData("text/plain", text);
|
|
4296
|
+
return true;
|
|
4273
4297
|
}
|
|
4274
4298
|
else {
|
|
4275
4299
|
captureCopy(view, text);
|
|
4300
|
+
return false;
|
|
4276
4301
|
}
|
|
4277
|
-
if (event.type == "cut" && !view.state.readOnly)
|
|
4278
|
-
view.dispatch({
|
|
4279
|
-
changes: ranges,
|
|
4280
|
-
scrollIntoView: true,
|
|
4281
|
-
userEvent: "delete.cut"
|
|
4282
|
-
});
|
|
4283
4302
|
};
|
|
4284
4303
|
const isFocusChange = /*@__PURE__*/Annotation.define();
|
|
4285
4304
|
function focusChangeTransaction(state, focus) {
|
|
@@ -4303,7 +4322,7 @@ function updateForFocusChange(view) {
|
|
|
4303
4322
|
}
|
|
4304
4323
|
}, 10);
|
|
4305
4324
|
}
|
|
4306
|
-
|
|
4325
|
+
observers.focus = view => {
|
|
4307
4326
|
view.inputState.lastFocusTime = Date.now();
|
|
4308
4327
|
// When focusing reset the scroll position, move it back to where it was
|
|
4309
4328
|
if (!view.scrollDOM.scrollTop && (view.inputState.lastScrollTop || view.inputState.lastScrollLeft)) {
|
|
@@ -4312,11 +4331,11 @@ handlers.focus = view => {
|
|
|
4312
4331
|
}
|
|
4313
4332
|
updateForFocusChange(view);
|
|
4314
4333
|
};
|
|
4315
|
-
|
|
4334
|
+
observers.blur = view => {
|
|
4316
4335
|
view.observer.clearSelectionRange();
|
|
4317
4336
|
updateForFocusChange(view);
|
|
4318
4337
|
};
|
|
4319
|
-
|
|
4338
|
+
observers.compositionstart = observers.compositionupdate = view => {
|
|
4320
4339
|
if (view.inputState.compositionFirstChange == null)
|
|
4321
4340
|
view.inputState.compositionFirstChange = true;
|
|
4322
4341
|
if (view.inputState.composing < 0) {
|
|
@@ -4324,7 +4343,7 @@ handlers.compositionstart = handlers.compositionupdate = view => {
|
|
|
4324
4343
|
view.inputState.composing = 0;
|
|
4325
4344
|
}
|
|
4326
4345
|
};
|
|
4327
|
-
|
|
4346
|
+
observers.compositionend = view => {
|
|
4328
4347
|
view.inputState.composing = -1;
|
|
4329
4348
|
view.inputState.compositionEndedAt = Date.now();
|
|
4330
4349
|
view.inputState.compositionPendingKey = true;
|
|
@@ -4348,7 +4367,7 @@ handlers.compositionend = view => {
|
|
|
4348
4367
|
}, 50);
|
|
4349
4368
|
}
|
|
4350
4369
|
};
|
|
4351
|
-
|
|
4370
|
+
observers.contextmenu = view => {
|
|
4352
4371
|
view.inputState.lastContextMenu = Date.now();
|
|
4353
4372
|
};
|
|
4354
4373
|
handlers.beforeinput = (view, event) => {
|
|
@@ -4377,6 +4396,7 @@ handlers.beforeinput = (view, event) => {
|
|
|
4377
4396
|
}, 100);
|
|
4378
4397
|
}
|
|
4379
4398
|
}
|
|
4399
|
+
return false;
|
|
4380
4400
|
};
|
|
4381
4401
|
const appliedFirefoxHack = /*@__PURE__*/new Set;
|
|
4382
4402
|
// In Firefox, when cut/copy handlers are added to the document, that
|
|
@@ -5046,14 +5066,13 @@ class NodeBuilder {
|
|
|
5046
5066
|
return line;
|
|
5047
5067
|
}
|
|
5048
5068
|
addBlock(block) {
|
|
5049
|
-
var _a;
|
|
5050
5069
|
this.enterLine();
|
|
5051
|
-
let
|
|
5052
|
-
if (
|
|
5070
|
+
let deco = block.deco;
|
|
5071
|
+
if (deco && deco.startSide > 0 && !this.isCovered)
|
|
5053
5072
|
this.ensureLine();
|
|
5054
5073
|
this.nodes.push(block);
|
|
5055
5074
|
this.writtenTo = this.pos = this.pos + block.length;
|
|
5056
|
-
if (
|
|
5075
|
+
if (deco && deco.endSide > 0)
|
|
5057
5076
|
this.covering = block;
|
|
5058
5077
|
}
|
|
5059
5078
|
addLineDeco(height, breaks, length) {
|
|
@@ -6161,7 +6180,7 @@ function applyDOMChange(view, domChange) {
|
|
|
6161
6180
|
change = { from: sel.from, to: sel.to, insert: Text.of([" "]) };
|
|
6162
6181
|
}
|
|
6163
6182
|
if (change) {
|
|
6164
|
-
if (browser.ios && view.inputState.flushIOSKey(
|
|
6183
|
+
if (browser.ios && view.inputState.flushIOSKey())
|
|
6165
6184
|
return true;
|
|
6166
6185
|
// Android browsers don't fire reasonable key events for enter,
|
|
6167
6186
|
// backspace, or delete. So this detects changes that look like
|
|
@@ -6415,7 +6434,7 @@ class DOMObserver {
|
|
|
6415
6434
|
this.readSelectionRange();
|
|
6416
6435
|
}
|
|
6417
6436
|
onScrollChanged(e) {
|
|
6418
|
-
this.view.inputState.
|
|
6437
|
+
this.view.inputState.runHandlers("scroll", e);
|
|
6419
6438
|
if (this.intersecting)
|
|
6420
6439
|
this.view.measure();
|
|
6421
6440
|
}
|
|
@@ -6886,7 +6905,7 @@ class EditorView {
|
|
|
6886
6905
|
plugin.update(this);
|
|
6887
6906
|
this.observer = new DOMObserver(this);
|
|
6888
6907
|
this.inputState = new InputState(this);
|
|
6889
|
-
this.inputState.ensureHandlers(this
|
|
6908
|
+
this.inputState.ensureHandlers(this.plugins);
|
|
6890
6909
|
this.docView = new DocView(this);
|
|
6891
6910
|
this.mountStyles();
|
|
6892
6911
|
this.updateAttrs();
|
|
@@ -7028,7 +7047,7 @@ class EditorView {
|
|
|
7028
7047
|
for (let plugin of this.plugins)
|
|
7029
7048
|
plugin.update(this);
|
|
7030
7049
|
this.docView = new DocView(this);
|
|
7031
|
-
this.inputState.ensureHandlers(this
|
|
7050
|
+
this.inputState.ensureHandlers(this.plugins);
|
|
7032
7051
|
this.mountStyles();
|
|
7033
7052
|
this.updateAttrs();
|
|
7034
7053
|
this.bidiCache = [];
|
|
@@ -7060,7 +7079,7 @@ class EditorView {
|
|
|
7060
7079
|
plugin.destroy(this);
|
|
7061
7080
|
this.plugins = newPlugins;
|
|
7062
7081
|
this.pluginMap.clear();
|
|
7063
|
-
this.inputState.ensureHandlers(this
|
|
7082
|
+
this.inputState.ensureHandlers(this.plugins);
|
|
7064
7083
|
}
|
|
7065
7084
|
else {
|
|
7066
7085
|
for (let p of this.plugins)
|
|
@@ -7588,6 +7607,17 @@ class EditorView {
|
|
|
7588
7607
|
return ViewPlugin.define(() => ({}), { eventHandlers: handlers });
|
|
7589
7608
|
}
|
|
7590
7609
|
/**
|
|
7610
|
+
Create an extension that registers DOM event observers. Contrary
|
|
7611
|
+
to event [handlers](https://codemirror.net/6/docs/ref/#view.EditorView^domEventHandlers),
|
|
7612
|
+
observers can't be prevented from running by a higher-precedence
|
|
7613
|
+
handler returning true. They also don't prevent other handlers
|
|
7614
|
+
and observers from running when they return true, and should not
|
|
7615
|
+
call `preventDefault`.
|
|
7616
|
+
*/
|
|
7617
|
+
static domEventObservers(observers) {
|
|
7618
|
+
return ViewPlugin.define(() => ({}), { eventObservers: observers });
|
|
7619
|
+
}
|
|
7620
|
+
/**
|
|
7591
7621
|
Create a theme extension. The first argument can be a
|
|
7592
7622
|
[`style-mod`](https://github.com/marijnh/style-mod#documentation)
|
|
7593
7623
|
style spec providing the styles for the theme. These will be
|
|
@@ -8314,6 +8344,14 @@ function drawSelection(config = {}) {
|
|
|
8314
8344
|
nativeSelectionHidden.of(true)
|
|
8315
8345
|
];
|
|
8316
8346
|
}
|
|
8347
|
+
/**
|
|
8348
|
+
Retrieve the [`drawSelection`](https://codemirror.net/6/docs/ref/#view.drawSelection) configuration
|
|
8349
|
+
for this state. (Note that this will return a set of defaults even
|
|
8350
|
+
if `drawSelection` isn't enabled.)
|
|
8351
|
+
*/
|
|
8352
|
+
function getDrawSelectionConfig(state) {
|
|
8353
|
+
return state.facet(selectionConfig);
|
|
8354
|
+
}
|
|
8317
8355
|
function configChanged(update) {
|
|
8318
8356
|
return update.startState.facet(selectionConfig) != update.state.facet(selectionConfig);
|
|
8319
8357
|
}
|
|
@@ -8440,7 +8478,7 @@ const drawDropCursor = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
8440
8478
|
this.view.dispatch({ effects: setDropCursorPos.of(pos) });
|
|
8441
8479
|
}
|
|
8442
8480
|
}, {
|
|
8443
|
-
|
|
8481
|
+
eventObservers: {
|
|
8444
8482
|
dragover(event) {
|
|
8445
8483
|
this.setDropPos(this.view.posAtCoords({ x: event.clientX, y: event.clientY }));
|
|
8446
8484
|
},
|
|
@@ -8950,7 +8988,7 @@ function crosshairCursor(options = {}) {
|
|
|
8950
8988
|
}
|
|
8951
8989
|
}
|
|
8952
8990
|
}, {
|
|
8953
|
-
|
|
8991
|
+
eventObservers: {
|
|
8954
8992
|
keydown(e) {
|
|
8955
8993
|
this.set(e.keyCode == code || getter(e));
|
|
8956
8994
|
},
|
|
@@ -9138,6 +9176,8 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9138
9176
|
tooltipView.dom.remove();
|
|
9139
9177
|
(_a = tooltipView.destroy) === null || _a === void 0 ? void 0 : _a.call(tooltipView);
|
|
9140
9178
|
}
|
|
9179
|
+
if (this.parent)
|
|
9180
|
+
this.container.remove();
|
|
9141
9181
|
(_b = this.intersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
9142
9182
|
clearTimeout(this.measureTimeout);
|
|
9143
9183
|
}
|
|
@@ -9261,7 +9301,7 @@ const tooltipPlugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
|
9261
9301
|
}
|
|
9262
9302
|
}
|
|
9263
9303
|
}, {
|
|
9264
|
-
|
|
9304
|
+
eventObservers: {
|
|
9265
9305
|
scroll() { this.maybeMeasure(); }
|
|
9266
9306
|
}
|
|
9267
9307
|
});
|
|
@@ -9579,8 +9619,9 @@ re-positioning or CSS change affecting the editor) that could
|
|
|
9579
9619
|
invalidate the existing tooltip positions.
|
|
9580
9620
|
*/
|
|
9581
9621
|
function repositionTooltips(view) {
|
|
9582
|
-
|
|
9583
|
-
(
|
|
9622
|
+
let plugin = view.plugin(tooltipPlugin);
|
|
9623
|
+
if (plugin)
|
|
9624
|
+
plugin.maybeMeasure();
|
|
9584
9625
|
}
|
|
9585
9626
|
|
|
9586
9627
|
const panelConfig = /*@__PURE__*/Facet.define({
|
|
@@ -10283,4 +10324,4 @@ function highlightTrailingWhitespace() {
|
|
|
10283
10324
|
*/
|
|
10284
10325
|
const __test = { HeightMap, HeightOracle, MeasuredHeights, QueryType, ChangedRange, computeOrder, moveVisually };
|
|
10285
10326
|
|
|
10286
|
-
export { BidiSpan, BlockInfo, BlockType, Decoration, Direction, EditorView, GutterMarker, MatchDecorator, RectangleMarker, ViewPlugin, ViewUpdate, WidgetType, __test, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|
|
10327
|
+
export { BidiSpan, BlockInfo, BlockType, Decoration, Direction, EditorView, GutterMarker, MatchDecorator, RectangleMarker, ViewPlugin, ViewUpdate, WidgetType, __test, closeHoverTooltips, crosshairCursor, drawSelection, dropCursor, getDrawSelectionConfig, getPanel, getTooltip, gutter, gutterLineClass, gutters, hasHoverTooltips, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, highlightTrailingWhitespace, highlightWhitespace, hoverTooltip, keymap, layer, lineNumberMarkers, lineNumbers, logException, panels, placeholder, rectangularSelection, repositionTooltips, runScopeHandlers, scrollPastEnd, showPanel, showTooltip, tooltips };
|