@b9g/revise 0.1.2 → 0.1.3
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/contentarea.cjs +176 -61
- package/contentarea.cjs.map +1 -1
- package/contentarea.d.ts +37 -19
- package/contentarea.js +176 -61
- package/contentarea.js.map +1 -1
- package/edit.cjs +23 -12
- package/edit.cjs.map +1 -1
- package/edit.js +23 -12
- package/edit.js.map +1 -1
- package/keyer.cjs +35 -10
- package/keyer.cjs.map +1 -1
- package/keyer.d.ts +1 -1
- package/keyer.js +35 -10
- package/keyer.js.map +1 -1
- package/package.json +1 -1
package/contentarea.cjs
CHANGED
|
@@ -5,43 +5,40 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var edit = require('./edit.cjs');
|
|
6
6
|
|
|
7
7
|
/// <reference lib="dom" />
|
|
8
|
-
|
|
9
|
-
const NEWLINE = "\n";
|
|
10
|
-
class ContentEvent extends CustomEvent {
|
|
11
|
-
constructor(typeArg, eventInit) {
|
|
12
|
-
// Maybe we should do some runtime eventInit validation.
|
|
13
|
-
super(typeArg, { bubbles: true, ...eventInit });
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
/********************************************/
|
|
8
|
+
/***************************************************/
|
|
17
9
|
/*** ContentAreaElement private property symbols ***/
|
|
18
|
-
|
|
19
|
-
const _cache = Symbol.for("
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
10
|
+
/***************************************************/
|
|
11
|
+
const _cache = Symbol.for("ContentArea._cache");
|
|
12
|
+
const _observer = Symbol.for("ContentArea._observer");
|
|
13
|
+
const _onselectionchange = Symbol.for("ContentArea._onselectionchange");
|
|
14
|
+
const _value = Symbol.for("ContentArea._value");
|
|
15
|
+
const _selectionRange = Symbol.for("ContentArea._selectionRange");
|
|
16
|
+
const _staleValue = Symbol.for("ContentArea._staleValue");
|
|
17
|
+
const _staleSelectionRange = Symbol.for("ContentArea._slateSelectionRange");
|
|
18
|
+
const _compositionBuffer = Symbol.for("ContentArea._compositionBuffer");
|
|
19
|
+
const _compositionStartValue = Symbol.for("ContentArea._compositionStartValue");
|
|
20
|
+
const _compositionSelectionRange = Symbol.for("ContentArea._compositionSelectionRange");
|
|
24
21
|
class ContentAreaElement extends HTMLElement {
|
|
25
22
|
constructor() {
|
|
26
23
|
super();
|
|
27
24
|
this[_cache] = new Map();
|
|
28
|
-
this[_value] = "";
|
|
29
25
|
this[_observer] = new MutationObserver((records) => {
|
|
26
|
+
if (this[_compositionBuffer]) {
|
|
27
|
+
// Buffer mutations during composition but still process them to keep cache in sync
|
|
28
|
+
this[_compositionBuffer].push(...records);
|
|
29
|
+
}
|
|
30
30
|
validate(this, records);
|
|
31
31
|
});
|
|
32
|
-
this[_selectionStart] = 0;
|
|
33
32
|
this[_onselectionchange] = () => {
|
|
34
|
-
|
|
35
|
-
// edits to text nodes.
|
|
36
|
-
validate(this);
|
|
37
|
-
this[_selectionStart] = getSelectionRange(this).start;
|
|
33
|
+
this[_selectionRange] = getSelectionRange(this);
|
|
38
34
|
};
|
|
39
|
-
this
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
this[_value] = "";
|
|
36
|
+
this[_selectionRange] = { start: 0, end: 0, direction: "none" };
|
|
37
|
+
this[_staleValue] = undefined;
|
|
38
|
+
this[_staleSelectionRange] = undefined;
|
|
39
|
+
this[_compositionBuffer] = undefined;
|
|
40
|
+
this[_compositionStartValue] = undefined;
|
|
41
|
+
this[_compositionSelectionRange] = undefined;
|
|
45
42
|
}
|
|
46
43
|
/******************************/
|
|
47
44
|
/*** Custom Element methods ***/
|
|
@@ -51,7 +48,9 @@ class ContentAreaElement extends HTMLElement {
|
|
|
51
48
|
subtree: true,
|
|
52
49
|
childList: true,
|
|
53
50
|
characterData: true,
|
|
51
|
+
characterDataOldValue: true,
|
|
54
52
|
attributes: true,
|
|
53
|
+
attributeOldValue: true,
|
|
55
54
|
attributeFilter: [
|
|
56
55
|
"data-content",
|
|
57
56
|
// TODO: implement these attributes
|
|
@@ -59,10 +58,54 @@ class ContentAreaElement extends HTMLElement {
|
|
|
59
58
|
//"data-contentafter",
|
|
60
59
|
],
|
|
61
60
|
});
|
|
62
|
-
validate(this);
|
|
63
61
|
document.addEventListener("selectionchange", this[_onselectionchange],
|
|
64
62
|
// We use capture in an attempt to run before other event listeners.
|
|
65
63
|
true);
|
|
64
|
+
validate(this);
|
|
65
|
+
this[_onselectionchange]();
|
|
66
|
+
// Composition event handling
|
|
67
|
+
let processCompositionTimeout;
|
|
68
|
+
this.addEventListener("compositionstart", () => {
|
|
69
|
+
clearTimeout(processCompositionTimeout); // Cancel pending commit
|
|
70
|
+
if (processCompositionTimeout == null) {
|
|
71
|
+
this[_compositionBuffer] = [];
|
|
72
|
+
this[_compositionStartValue] = this[_value];
|
|
73
|
+
this[_compositionSelectionRange] = { ...this[_selectionRange] };
|
|
74
|
+
}
|
|
75
|
+
processCompositionTimeout = undefined;
|
|
76
|
+
});
|
|
77
|
+
const processComposition = () => {
|
|
78
|
+
if (this[_compositionBuffer] &&
|
|
79
|
+
this[_compositionBuffer].length > 0 &&
|
|
80
|
+
this[_compositionStartValue] !== undefined &&
|
|
81
|
+
this[_compositionSelectionRange] !== undefined) {
|
|
82
|
+
const edit$1 = edit.Edit.diff(this[_compositionStartValue], this[_value], this[_compositionSelectionRange].start);
|
|
83
|
+
const ev = new ContentEvent("contentchange", {
|
|
84
|
+
detail: { edit: edit$1, source: null, mutations: this[_compositionBuffer] }
|
|
85
|
+
});
|
|
86
|
+
this.dispatchEvent(ev);
|
|
87
|
+
this[_staleValue] = undefined;
|
|
88
|
+
this[_staleSelectionRange] = undefined;
|
|
89
|
+
}
|
|
90
|
+
this[_compositionBuffer] = undefined;
|
|
91
|
+
this[_compositionStartValue] = undefined;
|
|
92
|
+
this[_compositionSelectionRange] = undefined;
|
|
93
|
+
processCompositionTimeout = undefined;
|
|
94
|
+
};
|
|
95
|
+
this.addEventListener("compositionend", () => {
|
|
96
|
+
clearTimeout(processCompositionTimeout);
|
|
97
|
+
processCompositionTimeout = setTimeout(processComposition);
|
|
98
|
+
});
|
|
99
|
+
this.addEventListener("blur", () => {
|
|
100
|
+
clearTimeout(processCompositionTimeout);
|
|
101
|
+
processComposition();
|
|
102
|
+
});
|
|
103
|
+
this.addEventListener("keydown", (e) => {
|
|
104
|
+
if (e.key === "Escape" && this[_compositionBuffer]) {
|
|
105
|
+
clearTimeout(processCompositionTimeout);
|
|
106
|
+
processComposition();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
66
109
|
}
|
|
67
110
|
disconnectedCallback() {
|
|
68
111
|
this[_cache].clear();
|
|
@@ -76,11 +119,12 @@ class ContentAreaElement extends HTMLElement {
|
|
|
76
119
|
}
|
|
77
120
|
get value() {
|
|
78
121
|
validate(this);
|
|
79
|
-
return this[_value];
|
|
122
|
+
return this[_staleValue] == null ? this[_value] : this[_staleValue];
|
|
80
123
|
}
|
|
81
124
|
get selectionStart() {
|
|
82
125
|
validate(this);
|
|
83
|
-
|
|
126
|
+
const range = this[_staleSelectionRange] || this[_selectionRange];
|
|
127
|
+
return range.start;
|
|
84
128
|
}
|
|
85
129
|
set selectionStart(start) {
|
|
86
130
|
validate(this);
|
|
@@ -89,7 +133,8 @@ class ContentAreaElement extends HTMLElement {
|
|
|
89
133
|
}
|
|
90
134
|
get selectionEnd() {
|
|
91
135
|
validate(this);
|
|
92
|
-
|
|
136
|
+
const range = this[_staleSelectionRange] || this[_selectionRange];
|
|
137
|
+
return range.end;
|
|
93
138
|
}
|
|
94
139
|
set selectionEnd(end) {
|
|
95
140
|
validate(this);
|
|
@@ -98,13 +143,19 @@ class ContentAreaElement extends HTMLElement {
|
|
|
98
143
|
}
|
|
99
144
|
get selectionDirection() {
|
|
100
145
|
validate(this);
|
|
101
|
-
|
|
146
|
+
const range = this[_staleSelectionRange] || this[_selectionRange];
|
|
147
|
+
return range.direction;
|
|
102
148
|
}
|
|
103
149
|
set selectionDirection(direction) {
|
|
104
150
|
validate(this);
|
|
105
151
|
const { start, end } = getSelectionRange(this);
|
|
106
152
|
setSelectionRange(this, { start, end, direction });
|
|
107
153
|
}
|
|
154
|
+
getSelectionRange() {
|
|
155
|
+
validate(this);
|
|
156
|
+
const range = this[_staleSelectionRange] || this[_selectionRange];
|
|
157
|
+
return { ...range };
|
|
158
|
+
}
|
|
108
159
|
setSelectionRange(start, end, direction = "none") {
|
|
109
160
|
validate(this);
|
|
110
161
|
setSelectionRange(this, { start, end, direction });
|
|
@@ -121,6 +172,58 @@ class ContentAreaElement extends HTMLElement {
|
|
|
121
172
|
return validate(this, this[_observer].takeRecords(), source);
|
|
122
173
|
}
|
|
123
174
|
}
|
|
175
|
+
const PreventDefaultSource = Symbol.for("ContentArea.PreventDefaultSource");
|
|
176
|
+
class ContentEvent extends CustomEvent {
|
|
177
|
+
constructor(typeArg, eventInit) {
|
|
178
|
+
// Maybe we should do some runtime eventInit validation.
|
|
179
|
+
super(typeArg, { bubbles: true, ...eventInit });
|
|
180
|
+
}
|
|
181
|
+
preventDefault() {
|
|
182
|
+
if (this.defaultPrevented) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
super.preventDefault();
|
|
186
|
+
const area = this.target;
|
|
187
|
+
area[_staleValue] = area[_value];
|
|
188
|
+
area[_staleSelectionRange] = area[_selectionRange];
|
|
189
|
+
const records = this.detail.mutations;
|
|
190
|
+
for (let i = records.length - 1; i >= 0; i--) {
|
|
191
|
+
const record = records[i];
|
|
192
|
+
switch (record.type) {
|
|
193
|
+
case 'childList': {
|
|
194
|
+
for (let j = 0; j < record.addedNodes.length; j++) {
|
|
195
|
+
const node = record.addedNodes[j];
|
|
196
|
+
if (node.parentNode) {
|
|
197
|
+
node.parentNode.removeChild(node);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (let j = 0; j < record.removedNodes.length; j++) {
|
|
201
|
+
const node = record.removedNodes[j];
|
|
202
|
+
record.target.insertBefore(node, record.nextSibling);
|
|
203
|
+
}
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
case 'characterData': {
|
|
207
|
+
if (record.oldValue !== null) {
|
|
208
|
+
record.target.data = record.oldValue;
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case 'attributes': {
|
|
213
|
+
if (record.oldValue === null) {
|
|
214
|
+
record.target.removeAttribute(record.attributeName);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
record.target.setAttribute(record.attributeName, record.oldValue);
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const records1 = (area)[_observer].takeRecords();
|
|
224
|
+
validate(area, records1, PreventDefaultSource);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
124
227
|
/*** NodeInfo.flags ***/
|
|
125
228
|
/** Whether the node is old. */
|
|
126
229
|
const IS_OLD = 1 << 0;
|
|
@@ -135,9 +238,9 @@ const APPENDS_NEWLINE = 1 << 4;
|
|
|
135
238
|
/** Data associated with the child nodes of a ContentAreaElement. */
|
|
136
239
|
class NodeInfo {
|
|
137
240
|
constructor(offset) {
|
|
241
|
+
this.f = 0;
|
|
138
242
|
this.offset = offset;
|
|
139
243
|
this.length = 0;
|
|
140
|
-
this.flags = 0;
|
|
141
244
|
}
|
|
142
245
|
}
|
|
143
246
|
/**
|
|
@@ -153,14 +256,23 @@ function validate(_this, records = _this[_observer].takeRecords(), source = null
|
|
|
153
256
|
if (typeof _this !== "object" || _this[_cache] == null) {
|
|
154
257
|
throw new TypeError("this is not a ContentAreaElement");
|
|
155
258
|
}
|
|
259
|
+
else if (!document.contains(_this)) {
|
|
260
|
+
throw new Error("ContentArea cannot be read before it is inserted into the DOM");
|
|
261
|
+
}
|
|
156
262
|
if (!invalidate(_this, records)) {
|
|
157
263
|
return false;
|
|
158
264
|
}
|
|
159
265
|
const oldValue = _this[_value];
|
|
160
|
-
const edit = diff(_this, oldValue, _this[
|
|
266
|
+
const edit = diff(_this, oldValue, _this[_selectionRange].start);
|
|
161
267
|
_this[_value] = edit.apply(oldValue);
|
|
162
|
-
|
|
163
|
-
|
|
268
|
+
_this[_selectionRange] = getSelectionRange(_this);
|
|
269
|
+
// Don't dispatch events during composition or preventDefault operations
|
|
270
|
+
if (source !== PreventDefaultSource && !_this[_compositionBuffer]) {
|
|
271
|
+
const ev = new ContentEvent("contentchange", { detail: { edit, source, mutations: records } });
|
|
272
|
+
_this.dispatchEvent(ev);
|
|
273
|
+
_this[_staleValue] = undefined;
|
|
274
|
+
_this[_staleSelectionRange] = undefined;
|
|
275
|
+
}
|
|
164
276
|
return true;
|
|
165
277
|
}
|
|
166
278
|
function invalidate(_this, records) {
|
|
@@ -177,7 +289,8 @@ function invalidate(_this, records) {
|
|
|
177
289
|
// We make sure all added and removed nodes and their children are deleted
|
|
178
290
|
// from the cache in case of any weirdness where nodes have been moved.
|
|
179
291
|
for (let j = 0; j < record.addedNodes.length; j++) {
|
|
180
|
-
|
|
292
|
+
const addedNode = record.addedNodes[j];
|
|
293
|
+
clear(addedNode, cache);
|
|
181
294
|
}
|
|
182
295
|
for (let j = 0; j < record.removedNodes.length; j++) {
|
|
183
296
|
clear(record.removedNodes[j], cache);
|
|
@@ -197,14 +310,14 @@ function invalidate(_this, records) {
|
|
|
197
310
|
}
|
|
198
311
|
const nodeInfo = cache.get(node);
|
|
199
312
|
if (nodeInfo) {
|
|
200
|
-
nodeInfo.
|
|
313
|
+
nodeInfo.f &= ~IS_VALID;
|
|
201
314
|
}
|
|
202
315
|
invalid = true;
|
|
203
316
|
}
|
|
204
317
|
}
|
|
205
318
|
if (invalid) {
|
|
206
319
|
const nodeInfo = cache.get(_this);
|
|
207
|
-
nodeInfo.
|
|
320
|
+
nodeInfo.f &= ~IS_VALID;
|
|
208
321
|
}
|
|
209
322
|
return invalid;
|
|
210
323
|
}
|
|
@@ -218,6 +331,8 @@ function clear(parent, cache) {
|
|
|
218
331
|
cache.delete(node);
|
|
219
332
|
}
|
|
220
333
|
}
|
|
334
|
+
// TODO: custom newlines?
|
|
335
|
+
const NEWLINE = "\n";
|
|
221
336
|
// THIS IS THE MOST COMPLICATED FUNCTION IN THE LIBRARY!
|
|
222
337
|
/**
|
|
223
338
|
* This function both returns an edit which represents changes to the
|
|
@@ -245,7 +360,7 @@ function diff(_this, oldValue, oldSelectionStart) {
|
|
|
245
360
|
if (nodeInfo === undefined) {
|
|
246
361
|
cache.set(node, (nodeInfo = new NodeInfo(offset)));
|
|
247
362
|
if (isBlocklikeElement(node)) {
|
|
248
|
-
nodeInfo.
|
|
363
|
+
nodeInfo.f |= IS_BLOCKLIKE;
|
|
249
364
|
}
|
|
250
365
|
}
|
|
251
366
|
else {
|
|
@@ -261,26 +376,26 @@ function diff(_this, oldValue, oldSelectionStart) {
|
|
|
261
376
|
}
|
|
262
377
|
nodeInfo.offset = offset;
|
|
263
378
|
}
|
|
264
|
-
if (offset && !hasNewline && nodeInfo.
|
|
379
|
+
if (offset && !hasNewline && nodeInfo.f & IS_BLOCKLIKE) {
|
|
265
380
|
// Block-like elements prepend a newline when they appear after text or
|
|
266
381
|
// inline elements.
|
|
267
382
|
hasNewline = true;
|
|
268
383
|
offset += NEWLINE.length;
|
|
269
384
|
value += NEWLINE;
|
|
270
|
-
if (nodeInfo.
|
|
385
|
+
if (nodeInfo.f & PREPENDS_NEWLINE) {
|
|
271
386
|
oldIndex += NEWLINE.length;
|
|
272
387
|
}
|
|
273
|
-
nodeInfo.
|
|
388
|
+
nodeInfo.f |= PREPENDS_NEWLINE;
|
|
274
389
|
}
|
|
275
390
|
else {
|
|
276
|
-
if (nodeInfo.
|
|
391
|
+
if (nodeInfo.f & PREPENDS_NEWLINE) {
|
|
277
392
|
// deletion detected
|
|
278
393
|
oldIndex += NEWLINE.length;
|
|
279
394
|
}
|
|
280
|
-
nodeInfo.
|
|
395
|
+
nodeInfo.f &= ~PREPENDS_NEWLINE;
|
|
281
396
|
}
|
|
282
397
|
descending = false;
|
|
283
|
-
if (nodeInfo.
|
|
398
|
+
if (nodeInfo.f & IS_VALID) {
|
|
284
399
|
// The node and its children are unchanged, so we read from the length.
|
|
285
400
|
if (nodeInfo.length) {
|
|
286
401
|
value += oldValue.slice(oldIndex, oldIndex + nodeInfo.length);
|
|
@@ -298,7 +413,7 @@ function diff(_this, oldValue, oldSelectionStart) {
|
|
|
298
413
|
offset += text.length;
|
|
299
414
|
hasNewline = text.endsWith(NEWLINE);
|
|
300
415
|
}
|
|
301
|
-
if (nodeInfo.
|
|
416
|
+
if (nodeInfo.f & IS_OLD) {
|
|
302
417
|
oldIndex += nodeInfo.length;
|
|
303
418
|
}
|
|
304
419
|
}
|
|
@@ -309,7 +424,7 @@ function diff(_this, oldValue, oldSelectionStart) {
|
|
|
309
424
|
offset += text.length;
|
|
310
425
|
hasNewline = text.endsWith(NEWLINE);
|
|
311
426
|
}
|
|
312
|
-
if (nodeInfo.
|
|
427
|
+
if (nodeInfo.f & IS_OLD) {
|
|
313
428
|
oldIndex += nodeInfo.length;
|
|
314
429
|
}
|
|
315
430
|
}
|
|
@@ -317,7 +432,7 @@ function diff(_this, oldValue, oldSelectionStart) {
|
|
|
317
432
|
value += NEWLINE;
|
|
318
433
|
offset += NEWLINE.length;
|
|
319
434
|
hasNewline = true;
|
|
320
|
-
if (nodeInfo.
|
|
435
|
+
if (nodeInfo.f & IS_OLD) {
|
|
321
436
|
oldIndex += nodeInfo.length;
|
|
322
437
|
}
|
|
323
438
|
}
|
|
@@ -337,7 +452,7 @@ function diff(_this, oldValue, oldSelectionStart) {
|
|
|
337
452
|
}
|
|
338
453
|
// If the child node prepends a newline, add to offset to increase the
|
|
339
454
|
// length of the parent node.
|
|
340
|
-
if (nodeInfo.
|
|
455
|
+
if (nodeInfo.f & PREPENDS_NEWLINE) {
|
|
341
456
|
offset += NEWLINE.length;
|
|
342
457
|
}
|
|
343
458
|
({ nodeInfo, oldIndexRelative } = stack.pop());
|
|
@@ -345,21 +460,21 @@ function diff(_this, oldValue, oldSelectionStart) {
|
|
|
345
460
|
}
|
|
346
461
|
if (!descending) {
|
|
347
462
|
// POST-ORDER LOGIC
|
|
348
|
-
if (!(nodeInfo.
|
|
463
|
+
if (!(nodeInfo.f & IS_VALID)) {
|
|
349
464
|
// TODO: Figure out if we should always recalculate APPENDS_NEWLINE???
|
|
350
|
-
if (!hasNewline && nodeInfo.
|
|
465
|
+
if (!hasNewline && nodeInfo.f & IS_BLOCKLIKE) {
|
|
351
466
|
value += NEWLINE;
|
|
352
467
|
offset += NEWLINE.length;
|
|
353
468
|
hasNewline = true;
|
|
354
|
-
nodeInfo.
|
|
469
|
+
nodeInfo.f |= APPENDS_NEWLINE;
|
|
355
470
|
}
|
|
356
471
|
else {
|
|
357
|
-
nodeInfo.
|
|
472
|
+
nodeInfo.f &= ~APPENDS_NEWLINE;
|
|
358
473
|
}
|
|
359
474
|
nodeInfo.length = offset - nodeInfo.offset;
|
|
360
|
-
nodeInfo.
|
|
475
|
+
nodeInfo.f |= IS_VALID;
|
|
361
476
|
}
|
|
362
|
-
nodeInfo.
|
|
477
|
+
nodeInfo.f |= IS_OLD;
|
|
363
478
|
descending = !!walker.nextSibling();
|
|
364
479
|
if (!descending) {
|
|
365
480
|
if (walker.currentNode === _this) {
|
|
@@ -431,7 +546,7 @@ function indexAt(_this, node, offset) {
|
|
|
431
546
|
else if (offset >= node.childNodes.length) {
|
|
432
547
|
const nodeInfo = cache.get(node);
|
|
433
548
|
index =
|
|
434
|
-
nodeInfo.
|
|
549
|
+
nodeInfo.f & APPENDS_NEWLINE
|
|
435
550
|
? nodeInfo.length - NEWLINE.length
|
|
436
551
|
: nodeInfo.length;
|
|
437
552
|
}
|
|
@@ -449,14 +564,14 @@ function indexAt(_this, node, offset) {
|
|
|
449
564
|
// If the offset references an element which prepends a newline
|
|
450
565
|
// ("hello<div>world</div>"), we have to start from -1 because the
|
|
451
566
|
// element’s info.offset will not account for the newline.
|
|
452
|
-
index = nodeInfo.
|
|
567
|
+
index = nodeInfo.f & PREPENDS_NEWLINE ? -1 : 0;
|
|
453
568
|
}
|
|
454
569
|
}
|
|
455
570
|
}
|
|
456
571
|
for (; node !== _this; node = node.parentNode) {
|
|
457
572
|
const nodeInfo = cache.get(node);
|
|
458
573
|
index += nodeInfo.offset;
|
|
459
|
-
if (nodeInfo.
|
|
574
|
+
if (nodeInfo.f & PREPENDS_NEWLINE) {
|
|
460
575
|
index += NEWLINE.length;
|
|
461
576
|
}
|
|
462
577
|
}
|
|
@@ -487,7 +602,7 @@ function findNodeOffset(_this, index) {
|
|
|
487
602
|
if (nodeInfo == null) {
|
|
488
603
|
return nodeOffsetFromChild(node, index > 0);
|
|
489
604
|
}
|
|
490
|
-
if (nodeInfo.
|
|
605
|
+
if (nodeInfo.f & PREPENDS_NEWLINE) {
|
|
491
606
|
index -= 1;
|
|
492
607
|
}
|
|
493
608
|
if (index === nodeInfo.length && node.nodeType === Node.TEXT_NODE) {
|
|
@@ -586,7 +701,7 @@ function setSelectionRange(_this, { start, end, direction }) {
|
|
|
586
701
|
selection.collapse(anchorNode, anchorOffset);
|
|
587
702
|
}
|
|
588
703
|
else {
|
|
589
|
-
// This method is not implemented in IE.
|
|
704
|
+
// NOTE: This method is not implemented in IE.
|
|
590
705
|
selection.setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
|
|
591
706
|
}
|
|
592
707
|
}
|