Diffdown is a real-time collaborative Markdown editor/previewer built on the AT Protocol diffdown.com
at 864c8fd63cccd160a05f67a7ce42eac86768c97c 3920 lines 145 kB view raw
1'use strict'; 2 3var findClusterBreak$1 = require('@marijn/find-cluster-break'); 4 5/** 6The data structure for documents. @nonabstract 7*/ 8class Text { 9 /** 10 Get the line description around the given position. 11 */ 12 lineAt(pos) { 13 if (pos < 0 || pos > this.length) 14 throw new RangeError(`Invalid position ${pos} in document of length ${this.length}`); 15 return this.lineInner(pos, false, 1, 0); 16 } 17 /** 18 Get the description for the given (1-based) line number. 19 */ 20 line(n) { 21 if (n < 1 || n > this.lines) 22 throw new RangeError(`Invalid line number ${n} in ${this.lines}-line document`); 23 return this.lineInner(n, true, 1, 0); 24 } 25 /** 26 Replace a range of the text with the given content. 27 */ 28 replace(from, to, text) { 29 [from, to] = clip(this, from, to); 30 let parts = []; 31 this.decompose(0, from, parts, 2 /* Open.To */); 32 if (text.length) 33 text.decompose(0, text.length, parts, 1 /* Open.From */ | 2 /* Open.To */); 34 this.decompose(to, this.length, parts, 1 /* Open.From */); 35 return TextNode.from(parts, this.length - (to - from) + text.length); 36 } 37 /** 38 Append another document to this one. 39 */ 40 append(other) { 41 return this.replace(this.length, this.length, other); 42 } 43 /** 44 Retrieve the text between the given points. 45 */ 46 slice(from, to = this.length) { 47 [from, to] = clip(this, from, to); 48 let parts = []; 49 this.decompose(from, to, parts, 0); 50 return TextNode.from(parts, to - from); 51 } 52 /** 53 Test whether this text is equal to another instance. 54 */ 55 eq(other) { 56 if (other == this) 57 return true; 58 if (other.length != this.length || other.lines != this.lines) 59 return false; 60 let start = this.scanIdentical(other, 1), end = this.length - this.scanIdentical(other, -1); 61 let a = new RawTextCursor(this), b = new RawTextCursor(other); 62 for (let skip = start, pos = start;;) { 63 a.next(skip); 64 b.next(skip); 65 skip = 0; 66 if (a.lineBreak != b.lineBreak || a.done != b.done || a.value != b.value) 67 return false; 68 pos += a.value.length; 69 if (a.done || pos >= end) 70 return true; 71 } 72 } 73 /** 74 Iterate over the text. When `dir` is `-1`, iteration happens 75 from end to start. This will return lines and the breaks between 76 them as separate strings. 77 */ 78 iter(dir = 1) { return new RawTextCursor(this, dir); } 79 /** 80 Iterate over a range of the text. When `from` > `to`, the 81 iterator will run in reverse. 82 */ 83 iterRange(from, to = this.length) { return new PartialTextCursor(this, from, to); } 84 /** 85 Return a cursor that iterates over the given range of lines, 86 _without_ returning the line breaks between, and yielding empty 87 strings for empty lines. 88 89 When `from` and `to` are given, they should be 1-based line numbers. 90 */ 91 iterLines(from, to) { 92 let inner; 93 if (from == null) { 94 inner = this.iter(); 95 } 96 else { 97 if (to == null) 98 to = this.lines + 1; 99 let start = this.line(from).from; 100 inner = this.iterRange(start, Math.max(start, to == this.lines + 1 ? this.length : to <= 1 ? 0 : this.line(to - 1).to)); 101 } 102 return new LineCursor(inner); 103 } 104 /** 105 Return the document as a string, using newline characters to 106 separate lines. 107 */ 108 toString() { return this.sliceString(0); } 109 /** 110 Convert the document to an array of lines (which can be 111 deserialized again via [`Text.of`](https://codemirror.net/6/docs/ref/#state.Text^of)). 112 */ 113 toJSON() { 114 let lines = []; 115 this.flatten(lines); 116 return lines; 117 } 118 /** 119 @internal 120 */ 121 constructor() { } 122 /** 123 Create a `Text` instance for the given array of lines. 124 */ 125 static of(text) { 126 if (text.length == 0) 127 throw new RangeError("A document must have at least one line"); 128 if (text.length == 1 && !text[0]) 129 return Text.empty; 130 return text.length <= 32 /* Tree.Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, [])); 131 } 132} 133// Leaves store an array of line strings. There are always line breaks 134// between these strings. Leaves are limited in size and have to be 135// contained in TextNode instances for bigger documents. 136class TextLeaf extends Text { 137 constructor(text, length = textLength(text)) { 138 super(); 139 this.text = text; 140 this.length = length; 141 } 142 get lines() { return this.text.length; } 143 get children() { return null; } 144 lineInner(target, isLine, line, offset) { 145 for (let i = 0;; i++) { 146 let string = this.text[i], end = offset + string.length; 147 if ((isLine ? line : end) >= target) 148 return new Line(offset, end, line, string); 149 offset = end + 1; 150 line++; 151 } 152 } 153 decompose(from, to, target, open) { 154 let text = from <= 0 && to >= this.length ? this 155 : new TextLeaf(sliceText(this.text, from, to), Math.min(to, this.length) - Math.max(0, from)); 156 if (open & 1 /* Open.From */) { 157 let prev = target.pop(); 158 let joined = appendText(text.text, prev.text.slice(), 0, text.length); 159 if (joined.length <= 32 /* Tree.Branch */) { 160 target.push(new TextLeaf(joined, prev.length + text.length)); 161 } 162 else { 163 let mid = joined.length >> 1; 164 target.push(new TextLeaf(joined.slice(0, mid)), new TextLeaf(joined.slice(mid))); 165 } 166 } 167 else { 168 target.push(text); 169 } 170 } 171 replace(from, to, text) { 172 if (!(text instanceof TextLeaf)) 173 return super.replace(from, to, text); 174 [from, to] = clip(this, from, to); 175 let lines = appendText(this.text, appendText(text.text, sliceText(this.text, 0, from)), to); 176 let newLen = this.length + text.length - (to - from); 177 if (lines.length <= 32 /* Tree.Branch */) 178 return new TextLeaf(lines, newLen); 179 return TextNode.from(TextLeaf.split(lines, []), newLen); 180 } 181 sliceString(from, to = this.length, lineSep = "\n") { 182 [from, to] = clip(this, from, to); 183 let result = ""; 184 for (let pos = 0, i = 0; pos <= to && i < this.text.length; i++) { 185 let line = this.text[i], end = pos + line.length; 186 if (pos > from && i) 187 result += lineSep; 188 if (from < end && to > pos) 189 result += line.slice(Math.max(0, from - pos), to - pos); 190 pos = end + 1; 191 } 192 return result; 193 } 194 flatten(target) { 195 for (let line of this.text) 196 target.push(line); 197 } 198 scanIdentical() { return 0; } 199 static split(text, target) { 200 let part = [], len = -1; 201 for (let line of text) { 202 part.push(line); 203 len += line.length + 1; 204 if (part.length == 32 /* Tree.Branch */) { 205 target.push(new TextLeaf(part, len)); 206 part = []; 207 len = -1; 208 } 209 } 210 if (len > -1) 211 target.push(new TextLeaf(part, len)); 212 return target; 213 } 214} 215// Nodes provide the tree structure of the `Text` type. They store a 216// number of other nodes or leaves, taking care to balance themselves 217// on changes. There are implied line breaks _between_ the children of 218// a node (but not before the first or after the last child). 219class TextNode extends Text { 220 constructor(children, length) { 221 super(); 222 this.children = children; 223 this.length = length; 224 this.lines = 0; 225 for (let child of children) 226 this.lines += child.lines; 227 } 228 lineInner(target, isLine, line, offset) { 229 for (let i = 0;; i++) { 230 let child = this.children[i], end = offset + child.length, endLine = line + child.lines - 1; 231 if ((isLine ? endLine : end) >= target) 232 return child.lineInner(target, isLine, line, offset); 233 offset = end + 1; 234 line = endLine + 1; 235 } 236 } 237 decompose(from, to, target, open) { 238 for (let i = 0, pos = 0; pos <= to && i < this.children.length; i++) { 239 let child = this.children[i], end = pos + child.length; 240 if (from <= end && to >= pos) { 241 let childOpen = open & ((pos <= from ? 1 /* Open.From */ : 0) | (end >= to ? 2 /* Open.To */ : 0)); 242 if (pos >= from && end <= to && !childOpen) 243 target.push(child); 244 else 245 child.decompose(from - pos, to - pos, target, childOpen); 246 } 247 pos = end + 1; 248 } 249 } 250 replace(from, to, text) { 251 [from, to] = clip(this, from, to); 252 if (text.lines < this.lines) 253 for (let i = 0, pos = 0; i < this.children.length; i++) { 254 let child = this.children[i], end = pos + child.length; 255 // Fast path: if the change only affects one child and the 256 // child's size remains in the acceptable range, only update 257 // that child 258 if (from >= pos && to <= end) { 259 let updated = child.replace(from - pos, to - pos, text); 260 let totalLines = this.lines - child.lines + updated.lines; 261 if (updated.lines < (totalLines >> (5 /* Tree.BranchShift */ - 1)) && 262 updated.lines > (totalLines >> (5 /* Tree.BranchShift */ + 1))) { 263 let copy = this.children.slice(); 264 copy[i] = updated; 265 return new TextNode(copy, this.length - (to - from) + text.length); 266 } 267 return super.replace(pos, end, updated); 268 } 269 pos = end + 1; 270 } 271 return super.replace(from, to, text); 272 } 273 sliceString(from, to = this.length, lineSep = "\n") { 274 [from, to] = clip(this, from, to); 275 let result = ""; 276 for (let i = 0, pos = 0; i < this.children.length && pos <= to; i++) { 277 let child = this.children[i], end = pos + child.length; 278 if (pos > from && i) 279 result += lineSep; 280 if (from < end && to > pos) 281 result += child.sliceString(from - pos, to - pos, lineSep); 282 pos = end + 1; 283 } 284 return result; 285 } 286 flatten(target) { 287 for (let child of this.children) 288 child.flatten(target); 289 } 290 scanIdentical(other, dir) { 291 if (!(other instanceof TextNode)) 292 return 0; 293 let length = 0; 294 let [iA, iB, eA, eB] = dir > 0 ? [0, 0, this.children.length, other.children.length] 295 : [this.children.length - 1, other.children.length - 1, -1, -1]; 296 for (;; iA += dir, iB += dir) { 297 if (iA == eA || iB == eB) 298 return length; 299 let chA = this.children[iA], chB = other.children[iB]; 300 if (chA != chB) 301 return length + chA.scanIdentical(chB, dir); 302 length += chA.length + 1; 303 } 304 } 305 static from(children, length = children.reduce((l, ch) => l + ch.length + 1, -1)) { 306 let lines = 0; 307 for (let ch of children) 308 lines += ch.lines; 309 if (lines < 32 /* Tree.Branch */) { 310 let flat = []; 311 for (let ch of children) 312 ch.flatten(flat); 313 return new TextLeaf(flat, length); 314 } 315 let chunk = Math.max(32 /* Tree.Branch */, lines >> 5 /* Tree.BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1; 316 let chunked = [], currentLines = 0, currentLen = -1, currentChunk = []; 317 function add(child) { 318 let last; 319 if (child.lines > maxChunk && child instanceof TextNode) { 320 for (let node of child.children) 321 add(node); 322 } 323 else if (child.lines > minChunk && (currentLines > minChunk || !currentLines)) { 324 flush(); 325 chunked.push(child); 326 } 327 else if (child instanceof TextLeaf && currentLines && 328 (last = currentChunk[currentChunk.length - 1]) instanceof TextLeaf && 329 child.lines + last.lines <= 32 /* Tree.Branch */) { 330 currentLines += child.lines; 331 currentLen += child.length + 1; 332 currentChunk[currentChunk.length - 1] = new TextLeaf(last.text.concat(child.text), last.length + 1 + child.length); 333 } 334 else { 335 if (currentLines + child.lines > chunk) 336 flush(); 337 currentLines += child.lines; 338 currentLen += child.length + 1; 339 currentChunk.push(child); 340 } 341 } 342 function flush() { 343 if (currentLines == 0) 344 return; 345 chunked.push(currentChunk.length == 1 ? currentChunk[0] : TextNode.from(currentChunk, currentLen)); 346 currentLen = -1; 347 currentLines = currentChunk.length = 0; 348 } 349 for (let child of children) 350 add(child); 351 flush(); 352 return chunked.length == 1 ? chunked[0] : new TextNode(chunked, length); 353 } 354} 355Text.empty = new TextLeaf([""], 0); 356function textLength(text) { 357 let length = -1; 358 for (let line of text) 359 length += line.length + 1; 360 return length; 361} 362function appendText(text, target, from = 0, to = 1e9) { 363 for (let pos = 0, i = 0, first = true; i < text.length && pos <= to; i++) { 364 let line = text[i], end = pos + line.length; 365 if (end >= from) { 366 if (end > to) 367 line = line.slice(0, to - pos); 368 if (pos < from) 369 line = line.slice(from - pos); 370 if (first) { 371 target[target.length - 1] += line; 372 first = false; 373 } 374 else 375 target.push(line); 376 } 377 pos = end + 1; 378 } 379 return target; 380} 381function sliceText(text, from, to) { 382 return appendText(text, [""], from, to); 383} 384class RawTextCursor { 385 constructor(text, dir = 1) { 386 this.dir = dir; 387 this.done = false; 388 this.lineBreak = false; 389 this.value = ""; 390 this.nodes = [text]; 391 this.offsets = [dir > 0 ? 1 : (text instanceof TextLeaf ? text.text.length : text.children.length) << 1]; 392 } 393 nextInner(skip, dir) { 394 this.done = this.lineBreak = false; 395 for (;;) { 396 let last = this.nodes.length - 1; 397 let top = this.nodes[last], offsetValue = this.offsets[last], offset = offsetValue >> 1; 398 let size = top instanceof TextLeaf ? top.text.length : top.children.length; 399 if (offset == (dir > 0 ? size : 0)) { 400 if (last == 0) { 401 this.done = true; 402 this.value = ""; 403 return this; 404 } 405 if (dir > 0) 406 this.offsets[last - 1]++; 407 this.nodes.pop(); 408 this.offsets.pop(); 409 } 410 else if ((offsetValue & 1) == (dir > 0 ? 0 : 1)) { 411 this.offsets[last] += dir; 412 if (skip == 0) { 413 this.lineBreak = true; 414 this.value = "\n"; 415 return this; 416 } 417 skip--; 418 } 419 else if (top instanceof TextLeaf) { 420 // Move to the next string 421 let next = top.text[offset + (dir < 0 ? -1 : 0)]; 422 this.offsets[last] += dir; 423 if (next.length > Math.max(0, skip)) { 424 this.value = skip == 0 ? next : dir > 0 ? next.slice(skip) : next.slice(0, next.length - skip); 425 return this; 426 } 427 skip -= next.length; 428 } 429 else { 430 let next = top.children[offset + (dir < 0 ? -1 : 0)]; 431 if (skip > next.length) { 432 skip -= next.length; 433 this.offsets[last] += dir; 434 } 435 else { 436 if (dir < 0) 437 this.offsets[last]--; 438 this.nodes.push(next); 439 this.offsets.push(dir > 0 ? 1 : (next instanceof TextLeaf ? next.text.length : next.children.length) << 1); 440 } 441 } 442 } 443 } 444 next(skip = 0) { 445 if (skip < 0) { 446 this.nextInner(-skip, (-this.dir)); 447 skip = this.value.length; 448 } 449 return this.nextInner(skip, this.dir); 450 } 451} 452class PartialTextCursor { 453 constructor(text, start, end) { 454 this.value = ""; 455 this.done = false; 456 this.cursor = new RawTextCursor(text, start > end ? -1 : 1); 457 this.pos = start > end ? text.length : 0; 458 this.from = Math.min(start, end); 459 this.to = Math.max(start, end); 460 } 461 nextInner(skip, dir) { 462 if (dir < 0 ? this.pos <= this.from : this.pos >= this.to) { 463 this.value = ""; 464 this.done = true; 465 return this; 466 } 467 skip += Math.max(0, dir < 0 ? this.pos - this.to : this.from - this.pos); 468 let limit = dir < 0 ? this.pos - this.from : this.to - this.pos; 469 if (skip > limit) 470 skip = limit; 471 limit -= skip; 472 let { value } = this.cursor.next(skip); 473 this.pos += (value.length + skip) * dir; 474 this.value = value.length <= limit ? value : dir < 0 ? value.slice(value.length - limit) : value.slice(0, limit); 475 this.done = !this.value; 476 return this; 477 } 478 next(skip = 0) { 479 if (skip < 0) 480 skip = Math.max(skip, this.from - this.pos); 481 else if (skip > 0) 482 skip = Math.min(skip, this.to - this.pos); 483 return this.nextInner(skip, this.cursor.dir); 484 } 485 get lineBreak() { return this.cursor.lineBreak && this.value != ""; } 486} 487class LineCursor { 488 constructor(inner) { 489 this.inner = inner; 490 this.afterBreak = true; 491 this.value = ""; 492 this.done = false; 493 } 494 next(skip = 0) { 495 let { done, lineBreak, value } = this.inner.next(skip); 496 if (done && this.afterBreak) { 497 this.value = ""; 498 this.afterBreak = false; 499 } 500 else if (done) { 501 this.done = true; 502 this.value = ""; 503 } 504 else if (lineBreak) { 505 if (this.afterBreak) { 506 this.value = ""; 507 } 508 else { 509 this.afterBreak = true; 510 this.next(); 511 } 512 } 513 else { 514 this.value = value; 515 this.afterBreak = false; 516 } 517 return this; 518 } 519 get lineBreak() { return false; } 520} 521if (typeof Symbol != "undefined") { 522 Text.prototype[Symbol.iterator] = function () { return this.iter(); }; 523 RawTextCursor.prototype[Symbol.iterator] = PartialTextCursor.prototype[Symbol.iterator] = 524 LineCursor.prototype[Symbol.iterator] = function () { return this; }; 525} 526/** 527This type describes a line in the document. It is created 528on-demand when lines are [queried](https://codemirror.net/6/docs/ref/#state.Text.lineAt). 529*/ 530class Line { 531 /** 532 @internal 533 */ 534 constructor( 535 /** 536 The position of the start of the line. 537 */ 538 from, 539 /** 540 The position at the end of the line (_before_ the line break, 541 or at the end of document for the last line). 542 */ 543 to, 544 /** 545 This line's line number (1-based). 546 */ 547 number, 548 /** 549 The line's content. 550 */ 551 text) { 552 this.from = from; 553 this.to = to; 554 this.number = number; 555 this.text = text; 556 } 557 /** 558 The length of the line (not including any line break after it). 559 */ 560 get length() { return this.to - this.from; } 561} 562function clip(text, from, to) { 563 from = Math.max(0, Math.min(text.length, from)); 564 return [from, Math.max(from, Math.min(text.length, to))]; 565} 566 567/** 568Returns a next grapheme cluster break _after_ (not equal to) 569`pos`, if `forward` is true, or before otherwise. Returns `pos` 570itself if no further cluster break is available in the string. 571Moves across surrogate pairs, extending characters (when 572`includeExtending` is true), characters joined with zero-width 573joiners, and flag emoji. 574*/ 575function findClusterBreak(str, pos, forward = true, includeExtending = true) { 576 return findClusterBreak$1.findClusterBreak(str, pos, forward, includeExtending); 577} 578function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; } 579function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; } 580/** 581Find the code point at the given position in a string (like the 582[`codePointAt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt) 583string method). 584*/ 585function codePointAt(str, pos) { 586 let code0 = str.charCodeAt(pos); 587 if (!surrogateHigh(code0) || pos + 1 == str.length) 588 return code0; 589 let code1 = str.charCodeAt(pos + 1); 590 if (!surrogateLow(code1)) 591 return code0; 592 return ((code0 - 0xd800) << 10) + (code1 - 0xdc00) + 0x10000; 593} 594/** 595Given a Unicode codepoint, return the JavaScript string that 596respresents it (like 597[`String.fromCodePoint`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)). 598*/ 599function fromCodePoint(code) { 600 if (code <= 0xffff) 601 return String.fromCharCode(code); 602 code -= 0x10000; 603 return String.fromCharCode((code >> 10) + 0xd800, (code & 1023) + 0xdc00); 604} 605/** 606The amount of positions a character takes up in a JavaScript string. 607*/ 608function codePointSize(code) { return code < 0x10000 ? 1 : 2; } 609 610const DefaultSplit = /\r\n?|\n/; 611/** 612Distinguishes different ways in which positions can be mapped. 613*/ 614exports.MapMode = void 0; 615(function (MapMode) { 616 /** 617 Map a position to a valid new position, even when its context 618 was deleted. 619 */ 620 MapMode[MapMode["Simple"] = 0] = "Simple"; 621 /** 622 Return null if deletion happens across the position. 623 */ 624 MapMode[MapMode["TrackDel"] = 1] = "TrackDel"; 625 /** 626 Return null if the character _before_ the position is deleted. 627 */ 628 MapMode[MapMode["TrackBefore"] = 2] = "TrackBefore"; 629 /** 630 Return null if the character _after_ the position is deleted. 631 */ 632 MapMode[MapMode["TrackAfter"] = 3] = "TrackAfter"; 633})(exports.MapMode || (exports.MapMode = {})); 634/** 635A change description is a variant of [change set](https://codemirror.net/6/docs/ref/#state.ChangeSet) 636that doesn't store the inserted text. As such, it can't be 637applied, but is cheaper to store and manipulate. 638*/ 639class ChangeDesc { 640 // Sections are encoded as pairs of integers. The first is the 641 // length in the current document, and the second is -1 for 642 // unaffected sections, and the length of the replacement content 643 // otherwise. So an insertion would be (0, n>0), a deletion (n>0, 644 // 0), and a replacement two positive numbers. 645 /** 646 @internal 647 */ 648 constructor( 649 /** 650 @internal 651 */ 652 sections) { 653 this.sections = sections; 654 } 655 /** 656 The length of the document before the change. 657 */ 658 get length() { 659 let result = 0; 660 for (let i = 0; i < this.sections.length; i += 2) 661 result += this.sections[i]; 662 return result; 663 } 664 /** 665 The length of the document after the change. 666 */ 667 get newLength() { 668 let result = 0; 669 for (let i = 0; i < this.sections.length; i += 2) { 670 let ins = this.sections[i + 1]; 671 result += ins < 0 ? this.sections[i] : ins; 672 } 673 return result; 674 } 675 /** 676 False when there are actual changes in this set. 677 */ 678 get empty() { return this.sections.length == 0 || this.sections.length == 2 && this.sections[1] < 0; } 679 /** 680 Iterate over the unchanged parts left by these changes. `posA` 681 provides the position of the range in the old document, `posB` 682 the new position in the changed document. 683 */ 684 iterGaps(f) { 685 for (let i = 0, posA = 0, posB = 0; i < this.sections.length;) { 686 let len = this.sections[i++], ins = this.sections[i++]; 687 if (ins < 0) { 688 f(posA, posB, len); 689 posB += len; 690 } 691 else { 692 posB += ins; 693 } 694 posA += len; 695 } 696 } 697 /** 698 Iterate over the ranges changed by these changes. (See 699 [`ChangeSet.iterChanges`](https://codemirror.net/6/docs/ref/#state.ChangeSet.iterChanges) for a 700 variant that also provides you with the inserted text.) 701 `fromA`/`toA` provides the extent of the change in the starting 702 document, `fromB`/`toB` the extent of the replacement in the 703 changed document. 704 705 When `individual` is true, adjacent changes (which are kept 706 separate for [position mapping](https://codemirror.net/6/docs/ref/#state.ChangeDesc.mapPos)) are 707 reported separately. 708 */ 709 iterChangedRanges(f, individual = false) { 710 iterChanges(this, f, individual); 711 } 712 /** 713 Get a description of the inverted form of these changes. 714 */ 715 get invertedDesc() { 716 let sections = []; 717 for (let i = 0; i < this.sections.length;) { 718 let len = this.sections[i++], ins = this.sections[i++]; 719 if (ins < 0) 720 sections.push(len, ins); 721 else 722 sections.push(ins, len); 723 } 724 return new ChangeDesc(sections); 725 } 726 /** 727 Compute the combined effect of applying another set of changes 728 after this one. The length of the document after this set should 729 match the length before `other`. 730 */ 731 composeDesc(other) { return this.empty ? other : other.empty ? this : composeSets(this, other); } 732 /** 733 Map this description, which should start with the same document 734 as `other`, over another set of changes, so that it can be 735 applied after it. When `before` is true, map as if the changes 736 in `this` happened before the ones in `other`. 737 */ 738 mapDesc(other, before = false) { return other.empty ? this : mapSet(this, other, before); } 739 mapPos(pos, assoc = -1, mode = exports.MapMode.Simple) { 740 let posA = 0, posB = 0; 741 for (let i = 0; i < this.sections.length;) { 742 let len = this.sections[i++], ins = this.sections[i++], endA = posA + len; 743 if (ins < 0) { 744 if (endA > pos) 745 return posB + (pos - posA); 746 posB += len; 747 } 748 else { 749 if (mode != exports.MapMode.Simple && endA >= pos && 750 (mode == exports.MapMode.TrackDel && posA < pos && endA > pos || 751 mode == exports.MapMode.TrackBefore && posA < pos || 752 mode == exports.MapMode.TrackAfter && endA > pos)) 753 return null; 754 if (endA > pos || endA == pos && assoc < 0 && !len) 755 return pos == posA || assoc < 0 ? posB : posB + ins; 756 posB += ins; 757 } 758 posA = endA; 759 } 760 if (pos > posA) 761 throw new RangeError(`Position ${pos} is out of range for changeset of length ${posA}`); 762 return posB; 763 } 764 /** 765 Check whether these changes touch a given range. When one of the 766 changes entirely covers the range, the string `"cover"` is 767 returned. 768 */ 769 touchesRange(from, to = from) { 770 for (let i = 0, pos = 0; i < this.sections.length && pos <= to;) { 771 let len = this.sections[i++], ins = this.sections[i++], end = pos + len; 772 if (ins >= 0 && pos <= to && end >= from) 773 return pos < from && end > to ? "cover" : true; 774 pos = end; 775 } 776 return false; 777 } 778 /** 779 @internal 780 */ 781 toString() { 782 let result = ""; 783 for (let i = 0; i < this.sections.length;) { 784 let len = this.sections[i++], ins = this.sections[i++]; 785 result += (result ? " " : "") + len + (ins >= 0 ? ":" + ins : ""); 786 } 787 return result; 788 } 789 /** 790 Serialize this change desc to a JSON-representable value. 791 */ 792 toJSON() { return this.sections; } 793 /** 794 Create a change desc from its JSON representation (as produced 795 by [`toJSON`](https://codemirror.net/6/docs/ref/#state.ChangeDesc.toJSON). 796 */ 797 static fromJSON(json) { 798 if (!Array.isArray(json) || json.length % 2 || json.some(a => typeof a != "number")) 799 throw new RangeError("Invalid JSON representation of ChangeDesc"); 800 return new ChangeDesc(json); 801 } 802 /** 803 @internal 804 */ 805 static create(sections) { return new ChangeDesc(sections); } 806} 807/** 808A change set represents a group of modifications to a document. It 809stores the document length, and can only be applied to documents 810with exactly that length. 811*/ 812class ChangeSet extends ChangeDesc { 813 constructor(sections, 814 /** 815 @internal 816 */ 817 inserted) { 818 super(sections); 819 this.inserted = inserted; 820 } 821 /** 822 Apply the changes to a document, returning the modified 823 document. 824 */ 825 apply(doc) { 826 if (this.length != doc.length) 827 throw new RangeError("Applying change set to a document with the wrong length"); 828 iterChanges(this, (fromA, toA, fromB, _toB, text) => doc = doc.replace(fromB, fromB + (toA - fromA), text), false); 829 return doc; 830 } 831 mapDesc(other, before = false) { return mapSet(this, other, before, true); } 832 /** 833 Given the document as it existed _before_ the changes, return a 834 change set that represents the inverse of this set, which could 835 be used to go from the document created by the changes back to 836 the document as it existed before the changes. 837 */ 838 invert(doc) { 839 let sections = this.sections.slice(), inserted = []; 840 for (let i = 0, pos = 0; i < sections.length; i += 2) { 841 let len = sections[i], ins = sections[i + 1]; 842 if (ins >= 0) { 843 sections[i] = ins; 844 sections[i + 1] = len; 845 let index = i >> 1; 846 while (inserted.length < index) 847 inserted.push(Text.empty); 848 inserted.push(len ? doc.slice(pos, pos + len) : Text.empty); 849 } 850 pos += len; 851 } 852 return new ChangeSet(sections, inserted); 853 } 854 /** 855 Combine two subsequent change sets into a single set. `other` 856 must start in the document produced by `this`. If `this` goes 857 `docA` → `docB` and `other` represents `docB` → `docC`, the 858 returned value will represent the change `docA` → `docC`. 859 */ 860 compose(other) { return this.empty ? other : other.empty ? this : composeSets(this, other, true); } 861 /** 862 Given another change set starting in the same document, maps this 863 change set over the other, producing a new change set that can be 864 applied to the document produced by applying `other`. When 865 `before` is `true`, order changes as if `this` comes before 866 `other`, otherwise (the default) treat `other` as coming first. 867 868 Given two changes `A` and `B`, `A.compose(B.map(A))` and 869 `B.compose(A.map(B, true))` will produce the same document. This 870 provides a basic form of [operational 871 transformation](https://en.wikipedia.org/wiki/Operational_transformation), 872 and can be used for collaborative editing. 873 */ 874 map(other, before = false) { return other.empty ? this : mapSet(this, other, before, true); } 875 /** 876 Iterate over the changed ranges in the document, calling `f` for 877 each, with the range in the original document (`fromA`-`toA`) 878 and the range that replaces it in the new document 879 (`fromB`-`toB`). 880 881 When `individual` is true, adjacent changes are reported 882 separately. 883 */ 884 iterChanges(f, individual = false) { 885 iterChanges(this, f, individual); 886 } 887 /** 888 Get a [change description](https://codemirror.net/6/docs/ref/#state.ChangeDesc) for this change 889 set. 890 */ 891 get desc() { return ChangeDesc.create(this.sections); } 892 /** 893 @internal 894 */ 895 filter(ranges) { 896 let resultSections = [], resultInserted = [], filteredSections = []; 897 let iter = new SectionIter(this); 898 done: for (let i = 0, pos = 0;;) { 899 let next = i == ranges.length ? 1e9 : ranges[i++]; 900 while (pos < next || pos == next && iter.len == 0) { 901 if (iter.done) 902 break done; 903 let len = Math.min(iter.len, next - pos); 904 addSection(filteredSections, len, -1); 905 let ins = iter.ins == -1 ? -1 : iter.off == 0 ? iter.ins : 0; 906 addSection(resultSections, len, ins); 907 if (ins > 0) 908 addInsert(resultInserted, resultSections, iter.text); 909 iter.forward(len); 910 pos += len; 911 } 912 let end = ranges[i++]; 913 while (pos < end) { 914 if (iter.done) 915 break done; 916 let len = Math.min(iter.len, end - pos); 917 addSection(resultSections, len, -1); 918 addSection(filteredSections, len, iter.ins == -1 ? -1 : iter.off == 0 ? iter.ins : 0); 919 iter.forward(len); 920 pos += len; 921 } 922 } 923 return { changes: new ChangeSet(resultSections, resultInserted), 924 filtered: ChangeDesc.create(filteredSections) }; 925 } 926 /** 927 Serialize this change set to a JSON-representable value. 928 */ 929 toJSON() { 930 let parts = []; 931 for (let i = 0; i < this.sections.length; i += 2) { 932 let len = this.sections[i], ins = this.sections[i + 1]; 933 if (ins < 0) 934 parts.push(len); 935 else if (ins == 0) 936 parts.push([len]); 937 else 938 parts.push([len].concat(this.inserted[i >> 1].toJSON())); 939 } 940 return parts; 941 } 942 /** 943 Create a change set for the given changes, for a document of the 944 given length, using `lineSep` as line separator. 945 */ 946 static of(changes, length, lineSep) { 947 let sections = [], inserted = [], pos = 0; 948 let total = null; 949 function flush(force = false) { 950 if (!force && !sections.length) 951 return; 952 if (pos < length) 953 addSection(sections, length - pos, -1); 954 let set = new ChangeSet(sections, inserted); 955 total = total ? total.compose(set.map(total)) : set; 956 sections = []; 957 inserted = []; 958 pos = 0; 959 } 960 function process(spec) { 961 if (Array.isArray(spec)) { 962 for (let sub of spec) 963 process(sub); 964 } 965 else if (spec instanceof ChangeSet) { 966 if (spec.length != length) 967 throw new RangeError(`Mismatched change set length (got ${spec.length}, expected ${length})`); 968 flush(); 969 total = total ? total.compose(spec.map(total)) : spec; 970 } 971 else { 972 let { from, to = from, insert } = spec; 973 if (from > to || from < 0 || to > length) 974 throw new RangeError(`Invalid change range ${from} to ${to} (in doc of length ${length})`); 975 let insText = !insert ? Text.empty : typeof insert == "string" ? Text.of(insert.split(lineSep || DefaultSplit)) : insert; 976 let insLen = insText.length; 977 if (from == to && insLen == 0) 978 return; 979 if (from < pos) 980 flush(); 981 if (from > pos) 982 addSection(sections, from - pos, -1); 983 addSection(sections, to - from, insLen); 984 addInsert(inserted, sections, insText); 985 pos = to; 986 } 987 } 988 process(changes); 989 flush(!total); 990 return total; 991 } 992 /** 993 Create an empty changeset of the given length. 994 */ 995 static empty(length) { 996 return new ChangeSet(length ? [length, -1] : [], []); 997 } 998 /** 999 Create a changeset from its JSON representation (as produced by 1000 [`toJSON`](https://codemirror.net/6/docs/ref/#state.ChangeSet.toJSON). 1001 */ 1002 static fromJSON(json) { 1003 if (!Array.isArray(json)) 1004 throw new RangeError("Invalid JSON representation of ChangeSet"); 1005 let sections = [], inserted = []; 1006 for (let i = 0; i < json.length; i++) { 1007 let part = json[i]; 1008 if (typeof part == "number") { 1009 sections.push(part, -1); 1010 } 1011 else if (!Array.isArray(part) || typeof part[0] != "number" || part.some((e, i) => i && typeof e != "string")) { 1012 throw new RangeError("Invalid JSON representation of ChangeSet"); 1013 } 1014 else if (part.length == 1) { 1015 sections.push(part[0], 0); 1016 } 1017 else { 1018 while (inserted.length < i) 1019 inserted.push(Text.empty); 1020 inserted[i] = Text.of(part.slice(1)); 1021 sections.push(part[0], inserted[i].length); 1022 } 1023 } 1024 return new ChangeSet(sections, inserted); 1025 } 1026 /** 1027 @internal 1028 */ 1029 static createSet(sections, inserted) { 1030 return new ChangeSet(sections, inserted); 1031 } 1032} 1033function addSection(sections, len, ins, forceJoin = false) { 1034 if (len == 0 && ins <= 0) 1035 return; 1036 let last = sections.length - 2; 1037 if (last >= 0 && ins <= 0 && ins == sections[last + 1]) 1038 sections[last] += len; 1039 else if (last >= 0 && len == 0 && sections[last] == 0) 1040 sections[last + 1] += ins; 1041 else if (forceJoin) { 1042 sections[last] += len; 1043 sections[last + 1] += ins; 1044 } 1045 else 1046 sections.push(len, ins); 1047} 1048function addInsert(values, sections, value) { 1049 if (value.length == 0) 1050 return; 1051 let index = (sections.length - 2) >> 1; 1052 if (index < values.length) { 1053 values[values.length - 1] = values[values.length - 1].append(value); 1054 } 1055 else { 1056 while (values.length < index) 1057 values.push(Text.empty); 1058 values.push(value); 1059 } 1060} 1061function iterChanges(desc, f, individual) { 1062 let inserted = desc.inserted; 1063 for (let posA = 0, posB = 0, i = 0; i < desc.sections.length;) { 1064 let len = desc.sections[i++], ins = desc.sections[i++]; 1065 if (ins < 0) { 1066 posA += len; 1067 posB += len; 1068 } 1069 else { 1070 let endA = posA, endB = posB, text = Text.empty; 1071 for (;;) { 1072 endA += len; 1073 endB += ins; 1074 if (ins && inserted) 1075 text = text.append(inserted[(i - 2) >> 1]); 1076 if (individual || i == desc.sections.length || desc.sections[i + 1] < 0) 1077 break; 1078 len = desc.sections[i++]; 1079 ins = desc.sections[i++]; 1080 } 1081 f(posA, endA, posB, endB, text); 1082 posA = endA; 1083 posB = endB; 1084 } 1085 } 1086} 1087function mapSet(setA, setB, before, mkSet = false) { 1088 // Produce a copy of setA that applies to the document after setB 1089 // has been applied (assuming both start at the same document). 1090 let sections = [], insert = mkSet ? [] : null; 1091 let a = new SectionIter(setA), b = new SectionIter(setB); 1092 // Iterate over both sets in parallel. inserted tracks, for changes 1093 // in A that have to be processed piece-by-piece, whether their 1094 // content has been inserted already, and refers to the section 1095 // index. 1096 for (let inserted = -1;;) { 1097 if (a.done && b.len || b.done && a.len) { 1098 throw new Error("Mismatched change set lengths"); 1099 } 1100 else if (a.ins == -1 && b.ins == -1) { 1101 // Move across ranges skipped by both sets. 1102 let len = Math.min(a.len, b.len); 1103 addSection(sections, len, -1); 1104 a.forward(len); 1105 b.forward(len); 1106 } 1107 else if (b.ins >= 0 && (a.ins < 0 || inserted == a.i || a.off == 0 && (b.len < a.len || b.len == a.len && !before))) { 1108 // If there's a change in B that comes before the next change in 1109 // A (ordered by start pos, then len, then before flag), skip 1110 // that (and process any changes in A it covers). 1111 let len = b.len; 1112 addSection(sections, b.ins, -1); 1113 while (len) { 1114 let piece = Math.min(a.len, len); 1115 if (a.ins >= 0 && inserted < a.i && a.len <= piece) { 1116 addSection(sections, 0, a.ins); 1117 if (insert) 1118 addInsert(insert, sections, a.text); 1119 inserted = a.i; 1120 } 1121 a.forward(piece); 1122 len -= piece; 1123 } 1124 b.next(); 1125 } 1126 else if (a.ins >= 0) { 1127 // Process the part of a change in A up to the start of the next 1128 // non-deletion change in B (if overlapping). 1129 let len = 0, left = a.len; 1130 while (left) { 1131 if (b.ins == -1) { 1132 let piece = Math.min(left, b.len); 1133 len += piece; 1134 left -= piece; 1135 b.forward(piece); 1136 } 1137 else if (b.ins == 0 && b.len < left) { 1138 left -= b.len; 1139 b.next(); 1140 } 1141 else { 1142 break; 1143 } 1144 } 1145 addSection(sections, len, inserted < a.i ? a.ins : 0); 1146 if (insert && inserted < a.i) 1147 addInsert(insert, sections, a.text); 1148 inserted = a.i; 1149 a.forward(a.len - left); 1150 } 1151 else if (a.done && b.done) { 1152 return insert ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(sections); 1153 } 1154 else { 1155 throw new Error("Mismatched change set lengths"); 1156 } 1157 } 1158} 1159function composeSets(setA, setB, mkSet = false) { 1160 let sections = []; 1161 let insert = mkSet ? [] : null; 1162 let a = new SectionIter(setA), b = new SectionIter(setB); 1163 for (let open = false;;) { 1164 if (a.done && b.done) { 1165 return insert ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(sections); 1166 } 1167 else if (a.ins == 0) { // Deletion in A 1168 addSection(sections, a.len, 0, open); 1169 a.next(); 1170 } 1171 else if (b.len == 0 && !b.done) { // Insertion in B 1172 addSection(sections, 0, b.ins, open); 1173 if (insert) 1174 addInsert(insert, sections, b.text); 1175 b.next(); 1176 } 1177 else if (a.done || b.done) { 1178 throw new Error("Mismatched change set lengths"); 1179 } 1180 else { 1181 let len = Math.min(a.len2, b.len), sectionLen = sections.length; 1182 if (a.ins == -1) { 1183 let insB = b.ins == -1 ? -1 : b.off ? 0 : b.ins; 1184 addSection(sections, len, insB, open); 1185 if (insert && insB) 1186 addInsert(insert, sections, b.text); 1187 } 1188 else if (b.ins == -1) { 1189 addSection(sections, a.off ? 0 : a.len, len, open); 1190 if (insert) 1191 addInsert(insert, sections, a.textBit(len)); 1192 } 1193 else { 1194 addSection(sections, a.off ? 0 : a.len, b.off ? 0 : b.ins, open); 1195 if (insert && !b.off) 1196 addInsert(insert, sections, b.text); 1197 } 1198 open = (a.ins > len || b.ins >= 0 && b.len > len) && (open || sections.length > sectionLen); 1199 a.forward2(len); 1200 b.forward(len); 1201 } 1202 } 1203} 1204class SectionIter { 1205 constructor(set) { 1206 this.set = set; 1207 this.i = 0; 1208 this.next(); 1209 } 1210 next() { 1211 let { sections } = this.set; 1212 if (this.i < sections.length) { 1213 this.len = sections[this.i++]; 1214 this.ins = sections[this.i++]; 1215 } 1216 else { 1217 this.len = 0; 1218 this.ins = -2; 1219 } 1220 this.off = 0; 1221 } 1222 get done() { return this.ins == -2; } 1223 get len2() { return this.ins < 0 ? this.len : this.ins; } 1224 get text() { 1225 let { inserted } = this.set, index = (this.i - 2) >> 1; 1226 return index >= inserted.length ? Text.empty : inserted[index]; 1227 } 1228 textBit(len) { 1229 let { inserted } = this.set, index = (this.i - 2) >> 1; 1230 return index >= inserted.length && !len ? Text.empty 1231 : inserted[index].slice(this.off, len == null ? undefined : this.off + len); 1232 } 1233 forward(len) { 1234 if (len == this.len) 1235 this.next(); 1236 else { 1237 this.len -= len; 1238 this.off += len; 1239 } 1240 } 1241 forward2(len) { 1242 if (this.ins == -1) 1243 this.forward(len); 1244 else if (len == this.ins) 1245 this.next(); 1246 else { 1247 this.ins -= len; 1248 this.off += len; 1249 } 1250 } 1251} 1252 1253/** 1254A single selection range. When 1255[`allowMultipleSelections`](https://codemirror.net/6/docs/ref/#state.EditorState^allowMultipleSelections) 1256is enabled, a [selection](https://codemirror.net/6/docs/ref/#state.EditorSelection) may hold 1257multiple ranges. By default, selections hold exactly one range. 1258*/ 1259class SelectionRange { 1260 constructor( 1261 /** 1262 The lower boundary of the range. 1263 */ 1264 from, 1265 /** 1266 The upper boundary of the range. 1267 */ 1268 to, flags) { 1269 this.from = from; 1270 this.to = to; 1271 this.flags = flags; 1272 } 1273 /** 1274 The anchor of the range—the side that doesn't move when you 1275 extend it. 1276 */ 1277 get anchor() { return this.flags & 32 /* RangeFlag.Inverted */ ? this.to : this.from; } 1278 /** 1279 The head of the range, which is moved when the range is 1280 [extended](https://codemirror.net/6/docs/ref/#state.SelectionRange.extend). 1281 */ 1282 get head() { return this.flags & 32 /* RangeFlag.Inverted */ ? this.from : this.to; } 1283 /** 1284 True when `anchor` and `head` are at the same position. 1285 */ 1286 get empty() { return this.from == this.to; } 1287 /** 1288 If this is a cursor that is explicitly associated with the 1289 character on one of its sides, this returns the side. -1 means 1290 the character before its position, 1 the character after, and 0 1291 means no association. 1292 */ 1293 get assoc() { return this.flags & 8 /* RangeFlag.AssocBefore */ ? -1 : this.flags & 16 /* RangeFlag.AssocAfter */ ? 1 : 0; } 1294 /** 1295 The bidirectional text level associated with this cursor, if 1296 any. 1297 */ 1298 get bidiLevel() { 1299 let level = this.flags & 7 /* RangeFlag.BidiLevelMask */; 1300 return level == 7 ? null : level; 1301 } 1302 /** 1303 The goal column (stored vertical offset) associated with a 1304 cursor. This is used to preserve the vertical position when 1305 [moving](https://codemirror.net/6/docs/ref/#view.EditorView.moveVertically) across 1306 lines of different length. 1307 */ 1308 get goalColumn() { 1309 let value = this.flags >> 6 /* RangeFlag.GoalColumnOffset */; 1310 return value == 16777215 /* RangeFlag.NoGoalColumn */ ? undefined : value; 1311 } 1312 /** 1313 Map this range through a change, producing a valid range in the 1314 updated document. 1315 */ 1316 map(change, assoc = -1) { 1317 let from, to; 1318 if (this.empty) { 1319 from = to = change.mapPos(this.from, assoc); 1320 } 1321 else { 1322 from = change.mapPos(this.from, 1); 1323 to = change.mapPos(this.to, -1); 1324 } 1325 return from == this.from && to == this.to ? this : new SelectionRange(from, to, this.flags); 1326 } 1327 /** 1328 Extend this range to cover at least `from` to `to`. 1329 */ 1330 extend(from, to = from) { 1331 if (from <= this.anchor && to >= this.anchor) 1332 return EditorSelection.range(from, to); 1333 let head = Math.abs(from - this.anchor) > Math.abs(to - this.anchor) ? from : to; 1334 return EditorSelection.range(this.anchor, head); 1335 } 1336 /** 1337 Compare this range to another range. 1338 */ 1339 eq(other, includeAssoc = false) { 1340 return this.anchor == other.anchor && this.head == other.head && this.goalColumn == other.goalColumn && 1341 (!includeAssoc || !this.empty || this.assoc == other.assoc); 1342 } 1343 /** 1344 Return a JSON-serializable object representing the range. 1345 */ 1346 toJSON() { return { anchor: this.anchor, head: this.head }; } 1347 /** 1348 Convert a JSON representation of a range to a `SelectionRange` 1349 instance. 1350 */ 1351 static fromJSON(json) { 1352 if (!json || typeof json.anchor != "number" || typeof json.head != "number") 1353 throw new RangeError("Invalid JSON representation for SelectionRange"); 1354 return EditorSelection.range(json.anchor, json.head); 1355 } 1356 /** 1357 @internal 1358 */ 1359 static create(from, to, flags) { 1360 return new SelectionRange(from, to, flags); 1361 } 1362} 1363/** 1364An editor selection holds one or more selection ranges. 1365*/ 1366class EditorSelection { 1367 constructor( 1368 /** 1369 The ranges in the selection, sorted by position. Ranges cannot 1370 overlap (but they may touch, if they aren't empty). 1371 */ 1372 ranges, 1373 /** 1374 The index of the _main_ range in the selection (which is 1375 usually the range that was added last). 1376 */ 1377 mainIndex) { 1378 this.ranges = ranges; 1379 this.mainIndex = mainIndex; 1380 } 1381 /** 1382 Map a selection through a change. Used to adjust the selection 1383 position for changes. 1384 */ 1385 map(change, assoc = -1) { 1386 if (change.empty) 1387 return this; 1388 return EditorSelection.create(this.ranges.map(r => r.map(change, assoc)), this.mainIndex); 1389 } 1390 /** 1391 Compare this selection to another selection. By default, ranges 1392 are compared only by position. When `includeAssoc` is true, 1393 cursor ranges must also have the same 1394 [`assoc`](https://codemirror.net/6/docs/ref/#state.SelectionRange.assoc) value. 1395 */ 1396 eq(other, includeAssoc = false) { 1397 if (this.ranges.length != other.ranges.length || 1398 this.mainIndex != other.mainIndex) 1399 return false; 1400 for (let i = 0; i < this.ranges.length; i++) 1401 if (!this.ranges[i].eq(other.ranges[i], includeAssoc)) 1402 return false; 1403 return true; 1404 } 1405 /** 1406 Get the primary selection range. Usually, you should make sure 1407 your code applies to _all_ ranges, by using methods like 1408 [`changeByRange`](https://codemirror.net/6/docs/ref/#state.EditorState.changeByRange). 1409 */ 1410 get main() { return this.ranges[this.mainIndex]; } 1411 /** 1412 Make sure the selection only has one range. Returns a selection 1413 holding only the main range from this selection. 1414 */ 1415 asSingle() { 1416 return this.ranges.length == 1 ? this : new EditorSelection([this.main], 0); 1417 } 1418 /** 1419 Extend this selection with an extra range. 1420 */ 1421 addRange(range, main = true) { 1422 return EditorSelection.create([range].concat(this.ranges), main ? 0 : this.mainIndex + 1); 1423 } 1424 /** 1425 Replace a given range with another range, and then normalize the 1426 selection to merge and sort ranges if necessary. 1427 */ 1428 replaceRange(range, which = this.mainIndex) { 1429 let ranges = this.ranges.slice(); 1430 ranges[which] = range; 1431 return EditorSelection.create(ranges, this.mainIndex); 1432 } 1433 /** 1434 Convert this selection to an object that can be serialized to 1435 JSON. 1436 */ 1437 toJSON() { 1438 return { ranges: this.ranges.map(r => r.toJSON()), main: this.mainIndex }; 1439 } 1440 /** 1441 Create a selection from a JSON representation. 1442 */ 1443 static fromJSON(json) { 1444 if (!json || !Array.isArray(json.ranges) || typeof json.main != "number" || json.main >= json.ranges.length) 1445 throw new RangeError("Invalid JSON representation for EditorSelection"); 1446 return new EditorSelection(json.ranges.map((r) => SelectionRange.fromJSON(r)), json.main); 1447 } 1448 /** 1449 Create a selection holding a single range. 1450 */ 1451 static single(anchor, head = anchor) { 1452 return new EditorSelection([EditorSelection.range(anchor, head)], 0); 1453 } 1454 /** 1455 Sort and merge the given set of ranges, creating a valid 1456 selection. 1457 */ 1458 static create(ranges, mainIndex = 0) { 1459 if (ranges.length == 0) 1460 throw new RangeError("A selection needs at least one range"); 1461 for (let pos = 0, i = 0; i < ranges.length; i++) { 1462 let range = ranges[i]; 1463 if (range.empty ? range.from <= pos : range.from < pos) 1464 return EditorSelection.normalized(ranges.slice(), mainIndex); 1465 pos = range.to; 1466 } 1467 return new EditorSelection(ranges, mainIndex); 1468 } 1469 /** 1470 Create a cursor selection range at the given position. You can 1471 safely ignore the optional arguments in most situations. 1472 */ 1473 static cursor(pos, assoc = 0, bidiLevel, goalColumn) { 1474 return SelectionRange.create(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 8 /* RangeFlag.AssocBefore */ : 16 /* RangeFlag.AssocAfter */) | 1475 (bidiLevel == null ? 7 : Math.min(6, bidiLevel)) | 1476 ((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 16777215 /* RangeFlag.NoGoalColumn */) << 6 /* RangeFlag.GoalColumnOffset */)); 1477 } 1478 /** 1479 Create a selection range. 1480 */ 1481 static range(anchor, head, goalColumn, bidiLevel) { 1482 let flags = ((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 16777215 /* RangeFlag.NoGoalColumn */) << 6 /* RangeFlag.GoalColumnOffset */) | 1483 (bidiLevel == null ? 7 : Math.min(6, bidiLevel)); 1484 return head < anchor ? SelectionRange.create(head, anchor, 32 /* RangeFlag.Inverted */ | 16 /* RangeFlag.AssocAfter */ | flags) 1485 : SelectionRange.create(anchor, head, (head > anchor ? 8 /* RangeFlag.AssocBefore */ : 0) | flags); 1486 } 1487 /** 1488 @internal 1489 */ 1490 static normalized(ranges, mainIndex = 0) { 1491 let main = ranges[mainIndex]; 1492 ranges.sort((a, b) => a.from - b.from); 1493 mainIndex = ranges.indexOf(main); 1494 for (let i = 1; i < ranges.length; i++) { 1495 let range = ranges[i], prev = ranges[i - 1]; 1496 if (range.empty ? range.from <= prev.to : range.from < prev.to) { 1497 let from = prev.from, to = Math.max(range.to, prev.to); 1498 if (i <= mainIndex) 1499 mainIndex--; 1500 ranges.splice(--i, 2, range.anchor > range.head ? EditorSelection.range(to, from) : EditorSelection.range(from, to)); 1501 } 1502 } 1503 return new EditorSelection(ranges, mainIndex); 1504 } 1505} 1506function checkSelection(selection, docLength) { 1507 for (let range of selection.ranges) 1508 if (range.to > docLength) 1509 throw new RangeError("Selection points outside of document"); 1510} 1511 1512let nextID = 0; 1513/** 1514A facet is a labeled value that is associated with an editor 1515state. It takes inputs from any number of extensions, and combines 1516those into a single output value. 1517 1518Examples of uses of facets are the [tab 1519size](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize), [editor 1520attributes](https://codemirror.net/6/docs/ref/#view.EditorView^editorAttributes), and [update 1521listeners](https://codemirror.net/6/docs/ref/#view.EditorView^updateListener). 1522 1523Note that `Facet` instances can be used anywhere where 1524[`FacetReader`](https://codemirror.net/6/docs/ref/#state.FacetReader) is expected. 1525*/ 1526class Facet { 1527 constructor( 1528 /** 1529 @internal 1530 */ 1531 combine, 1532 /** 1533 @internal 1534 */ 1535 compareInput, 1536 /** 1537 @internal 1538 */ 1539 compare, isStatic, enables) { 1540 this.combine = combine; 1541 this.compareInput = compareInput; 1542 this.compare = compare; 1543 this.isStatic = isStatic; 1544 /** 1545 @internal 1546 */ 1547 this.id = nextID++; 1548 this.default = combine([]); 1549 this.extensions = typeof enables == "function" ? enables(this) : enables; 1550 } 1551 /** 1552 Returns a facet reader for this facet, which can be used to 1553 [read](https://codemirror.net/6/docs/ref/#state.EditorState.facet) it but not to define values for it. 1554 */ 1555 get reader() { return this; } 1556 /** 1557 Define a new facet. 1558 */ 1559 static define(config = {}) { 1560 return new Facet(config.combine || ((a) => a), config.compareInput || ((a, b) => a === b), config.compare || (!config.combine ? sameArray : (a, b) => a === b), !!config.static, config.enables); 1561 } 1562 /** 1563 Returns an extension that adds the given value to this facet. 1564 */ 1565 of(value) { 1566 return new FacetProvider([], this, 0 /* Provider.Static */, value); 1567 } 1568 /** 1569 Create an extension that computes a value for the facet from a 1570 state. You must take care to declare the parts of the state that 1571 this value depends on, since your function is only called again 1572 for a new state when one of those parts changed. 1573 1574 In cases where your value depends only on a single field, you'll 1575 want to use the [`from`](https://codemirror.net/6/docs/ref/#state.Facet.from) method instead. 1576 */ 1577 compute(deps, get) { 1578 if (this.isStatic) 1579 throw new Error("Can't compute a static facet"); 1580 return new FacetProvider(deps, this, 1 /* Provider.Single */, get); 1581 } 1582 /** 1583 Create an extension that computes zero or more values for this 1584 facet from a state. 1585 */ 1586 computeN(deps, get) { 1587 if (this.isStatic) 1588 throw new Error("Can't compute a static facet"); 1589 return new FacetProvider(deps, this, 2 /* Provider.Multi */, get); 1590 } 1591 from(field, get) { 1592 if (!get) 1593 get = x => x; 1594 return this.compute([field], state => get(state.field(field))); 1595 } 1596} 1597function sameArray(a, b) { 1598 return a == b || a.length == b.length && a.every((e, i) => e === b[i]); 1599} 1600class FacetProvider { 1601 constructor(dependencies, facet, type, value) { 1602 this.dependencies = dependencies; 1603 this.facet = facet; 1604 this.type = type; 1605 this.value = value; 1606 this.id = nextID++; 1607 } 1608 dynamicSlot(addresses) { 1609 var _a; 1610 let getter = this.value; 1611 let compare = this.facet.compareInput; 1612 let id = this.id, idx = addresses[id] >> 1, multi = this.type == 2 /* Provider.Multi */; 1613 let depDoc = false, depSel = false, depAddrs = []; 1614 for (let dep of this.dependencies) { 1615 if (dep == "doc") 1616 depDoc = true; 1617 else if (dep == "selection") 1618 depSel = true; 1619 else if ((((_a = addresses[dep.id]) !== null && _a !== void 0 ? _a : 1) & 1) == 0) 1620 depAddrs.push(addresses[dep.id]); 1621 } 1622 return { 1623 create(state) { 1624 state.values[idx] = getter(state); 1625 return 1 /* SlotStatus.Changed */; 1626 }, 1627 update(state, tr) { 1628 if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) || ensureAll(state, depAddrs)) { 1629 let newVal = getter(state); 1630 if (multi ? !compareArray(newVal, state.values[idx], compare) : !compare(newVal, state.values[idx])) { 1631 state.values[idx] = newVal; 1632 return 1 /* SlotStatus.Changed */; 1633 } 1634 } 1635 return 0; 1636 }, 1637 reconfigure: (state, oldState) => { 1638 let newVal, oldAddr = oldState.config.address[id]; 1639 if (oldAddr != null) { 1640 let oldVal = getAddr(oldState, oldAddr); 1641 if (this.dependencies.every(dep => { 1642 return dep instanceof Facet ? oldState.facet(dep) === state.facet(dep) : 1643 dep instanceof StateField ? oldState.field(dep, false) == state.field(dep, false) : true; 1644 }) || (multi ? compareArray(newVal = getter(state), oldVal, compare) : compare(newVal = getter(state), oldVal))) { 1645 state.values[idx] = oldVal; 1646 return 0; 1647 } 1648 } 1649 else { 1650 newVal = getter(state); 1651 } 1652 state.values[idx] = newVal; 1653 return 1 /* SlotStatus.Changed */; 1654 } 1655 }; 1656 } 1657} 1658function compareArray(a, b, compare) { 1659 if (a.length != b.length) 1660 return false; 1661 for (let i = 0; i < a.length; i++) 1662 if (!compare(a[i], b[i])) 1663 return false; 1664 return true; 1665} 1666function ensureAll(state, addrs) { 1667 let changed = false; 1668 for (let addr of addrs) 1669 if (ensureAddr(state, addr) & 1 /* SlotStatus.Changed */) 1670 changed = true; 1671 return changed; 1672} 1673function dynamicFacetSlot(addresses, facet, providers) { 1674 let providerAddrs = providers.map(p => addresses[p.id]); 1675 let providerTypes = providers.map(p => p.type); 1676 let dynamic = providerAddrs.filter(p => !(p & 1)); 1677 let idx = addresses[facet.id] >> 1; 1678 function get(state) { 1679 let values = []; 1680 for (let i = 0; i < providerAddrs.length; i++) { 1681 let value = getAddr(state, providerAddrs[i]); 1682 if (providerTypes[i] == 2 /* Provider.Multi */) 1683 for (let val of value) 1684 values.push(val); 1685 else 1686 values.push(value); 1687 } 1688 return facet.combine(values); 1689 } 1690 return { 1691 create(state) { 1692 for (let addr of providerAddrs) 1693 ensureAddr(state, addr); 1694 state.values[idx] = get(state); 1695 return 1 /* SlotStatus.Changed */; 1696 }, 1697 update(state, tr) { 1698 if (!ensureAll(state, dynamic)) 1699 return 0; 1700 let value = get(state); 1701 if (facet.compare(value, state.values[idx])) 1702 return 0; 1703 state.values[idx] = value; 1704 return 1 /* SlotStatus.Changed */; 1705 }, 1706 reconfigure(state, oldState) { 1707 let depChanged = ensureAll(state, providerAddrs); 1708 let oldProviders = oldState.config.facets[facet.id], oldValue = oldState.facet(facet); 1709 if (oldProviders && !depChanged && sameArray(providers, oldProviders)) { 1710 state.values[idx] = oldValue; 1711 return 0; 1712 } 1713 let value = get(state); 1714 if (facet.compare(value, oldValue)) { 1715 state.values[idx] = oldValue; 1716 return 0; 1717 } 1718 state.values[idx] = value; 1719 return 1 /* SlotStatus.Changed */; 1720 } 1721 }; 1722} 1723const initField = Facet.define({ static: true }); 1724/** 1725Fields can store additional information in an editor state, and 1726keep it in sync with the rest of the state. 1727*/ 1728class StateField { 1729 constructor( 1730 /** 1731 @internal 1732 */ 1733 id, createF, updateF, compareF, 1734 /** 1735 @internal 1736 */ 1737 spec) { 1738 this.id = id; 1739 this.createF = createF; 1740 this.updateF = updateF; 1741 this.compareF = compareF; 1742 this.spec = spec; 1743 /** 1744 @internal 1745 */ 1746 this.provides = undefined; 1747 } 1748 /** 1749 Define a state field. 1750 */ 1751 static define(config) { 1752 let field = new StateField(nextID++, config.create, config.update, config.compare || ((a, b) => a === b), config); 1753 if (config.provide) 1754 field.provides = config.provide(field); 1755 return field; 1756 } 1757 create(state) { 1758 let init = state.facet(initField).find(i => i.field == this); 1759 return ((init === null || init === void 0 ? void 0 : init.create) || this.createF)(state); 1760 } 1761 /** 1762 @internal 1763 */ 1764 slot(addresses) { 1765 let idx = addresses[this.id] >> 1; 1766 return { 1767 create: (state) => { 1768 state.values[idx] = this.create(state); 1769 return 1 /* SlotStatus.Changed */; 1770 }, 1771 update: (state, tr) => { 1772 let oldVal = state.values[idx]; 1773 let value = this.updateF(oldVal, tr); 1774 if (this.compareF(oldVal, value)) 1775 return 0; 1776 state.values[idx] = value; 1777 return 1 /* SlotStatus.Changed */; 1778 }, 1779 reconfigure: (state, oldState) => { 1780 let init = state.facet(initField), oldInit = oldState.facet(initField), reInit; 1781 if ((reInit = init.find(i => i.field == this)) && reInit != oldInit.find(i => i.field == this)) { 1782 state.values[idx] = reInit.create(state); 1783 return 1 /* SlotStatus.Changed */; 1784 } 1785 if (oldState.config.address[this.id] != null) { 1786 state.values[idx] = oldState.field(this); 1787 return 0; 1788 } 1789 state.values[idx] = this.create(state); 1790 return 1 /* SlotStatus.Changed */; 1791 } 1792 }; 1793 } 1794 /** 1795 Returns an extension that enables this field and overrides the 1796 way it is initialized. Can be useful when you need to provide a 1797 non-default starting value for the field. 1798 */ 1799 init(create) { 1800 return [this, initField.of({ field: this, create })]; 1801 } 1802 /** 1803 State field instances can be used as 1804 [`Extension`](https://codemirror.net/6/docs/ref/#state.Extension) values to enable the field in a 1805 given state. 1806 */ 1807 get extension() { return this; } 1808} 1809const Prec_ = { lowest: 4, low: 3, default: 2, high: 1, highest: 0 }; 1810function prec(value) { 1811 return (ext) => new PrecExtension(ext, value); 1812} 1813/** 1814By default extensions are registered in the order they are found 1815in the flattened form of nested array that was provided. 1816Individual extension values can be assigned a precedence to 1817override this. Extensions that do not have a precedence set get 1818the precedence of the nearest parent with a precedence, or 1819[`default`](https://codemirror.net/6/docs/ref/#state.Prec.default) if there is no such parent. The 1820final ordering of extensions is determined by first sorting by 1821precedence and then by order within each precedence. 1822*/ 1823const Prec = { 1824 /** 1825 The highest precedence level, for extensions that should end up 1826 near the start of the precedence ordering. 1827 */ 1828 highest: prec(Prec_.highest), 1829 /** 1830 A higher-than-default precedence, for extensions that should 1831 come before those with default precedence. 1832 */ 1833 high: prec(Prec_.high), 1834 /** 1835 The default precedence, which is also used for extensions 1836 without an explicit precedence. 1837 */ 1838 default: prec(Prec_.default), 1839 /** 1840 A lower-than-default precedence. 1841 */ 1842 low: prec(Prec_.low), 1843 /** 1844 The lowest precedence level. Meant for things that should end up 1845 near the end of the extension order. 1846 */ 1847 lowest: prec(Prec_.lowest) 1848}; 1849class PrecExtension { 1850 constructor(inner, prec) { 1851 this.inner = inner; 1852 this.prec = prec; 1853 } 1854} 1855/** 1856Extension compartments can be used to make a configuration 1857dynamic. By [wrapping](https://codemirror.net/6/docs/ref/#state.Compartment.of) part of your 1858configuration in a compartment, you can later 1859[replace](https://codemirror.net/6/docs/ref/#state.Compartment.reconfigure) that part through a 1860transaction. 1861*/ 1862class Compartment { 1863 /** 1864 Create an instance of this compartment to add to your [state 1865 configuration](https://codemirror.net/6/docs/ref/#state.EditorStateConfig.extensions). 1866 */ 1867 of(ext) { return new CompartmentInstance(this, ext); } 1868 /** 1869 Create an [effect](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) that 1870 reconfigures this compartment. 1871 */ 1872 reconfigure(content) { 1873 return Compartment.reconfigure.of({ compartment: this, extension: content }); 1874 } 1875 /** 1876 Get the current content of the compartment in the state, or 1877 `undefined` if it isn't present. 1878 */ 1879 get(state) { 1880 return state.config.compartments.get(this); 1881 } 1882} 1883class CompartmentInstance { 1884 constructor(compartment, inner) { 1885 this.compartment = compartment; 1886 this.inner = inner; 1887 } 1888} 1889class Configuration { 1890 constructor(base, compartments, dynamicSlots, address, staticValues, facets) { 1891 this.base = base; 1892 this.compartments = compartments; 1893 this.dynamicSlots = dynamicSlots; 1894 this.address = address; 1895 this.staticValues = staticValues; 1896 this.facets = facets; 1897 this.statusTemplate = []; 1898 while (this.statusTemplate.length < dynamicSlots.length) 1899 this.statusTemplate.push(0 /* SlotStatus.Unresolved */); 1900 } 1901 staticFacet(facet) { 1902 let addr = this.address[facet.id]; 1903 return addr == null ? facet.default : this.staticValues[addr >> 1]; 1904 } 1905 static resolve(base, compartments, oldState) { 1906 let fields = []; 1907 let facets = Object.create(null); 1908 let newCompartments = new Map(); 1909 for (let ext of flatten(base, compartments, newCompartments)) { 1910 if (ext instanceof StateField) 1911 fields.push(ext); 1912 else 1913 (facets[ext.facet.id] || (facets[ext.facet.id] = [])).push(ext); 1914 } 1915 let address = Object.create(null); 1916 let staticValues = []; 1917 let dynamicSlots = []; 1918 for (let field of fields) { 1919 address[field.id] = dynamicSlots.length << 1; 1920 dynamicSlots.push(a => field.slot(a)); 1921 } 1922 let oldFacets = oldState === null || oldState === void 0 ? void 0 : oldState.config.facets; 1923 for (let id in facets) { 1924 let providers = facets[id], facet = providers[0].facet; 1925 let oldProviders = oldFacets && oldFacets[id] || []; 1926 if (providers.every(p => p.type == 0 /* Provider.Static */)) { 1927 address[facet.id] = (staticValues.length << 1) | 1; 1928 if (sameArray(oldProviders, providers)) { 1929 staticValues.push(oldState.facet(facet)); 1930 } 1931 else { 1932 let value = facet.combine(providers.map(p => p.value)); 1933 staticValues.push(oldState && facet.compare(value, oldState.facet(facet)) ? oldState.facet(facet) : value); 1934 } 1935 } 1936 else { 1937 for (let p of providers) { 1938 if (p.type == 0 /* Provider.Static */) { 1939 address[p.id] = (staticValues.length << 1) | 1; 1940 staticValues.push(p.value); 1941 } 1942 else { 1943 address[p.id] = dynamicSlots.length << 1; 1944 dynamicSlots.push(a => p.dynamicSlot(a)); 1945 } 1946 } 1947 address[facet.id] = dynamicSlots.length << 1; 1948 dynamicSlots.push(a => dynamicFacetSlot(a, facet, providers)); 1949 } 1950 } 1951 let dynamic = dynamicSlots.map(f => f(address)); 1952 return new Configuration(base, newCompartments, dynamic, address, staticValues, facets); 1953 } 1954} 1955function flatten(extension, compartments, newCompartments) { 1956 let result = [[], [], [], [], []]; 1957 let seen = new Map(); 1958 function inner(ext, prec) { 1959 let known = seen.get(ext); 1960 if (known != null) { 1961 if (known <= prec) 1962 return; 1963 let found = result[known].indexOf(ext); 1964 if (found > -1) 1965 result[known].splice(found, 1); 1966 if (ext instanceof CompartmentInstance) 1967 newCompartments.delete(ext.compartment); 1968 } 1969 seen.set(ext, prec); 1970 if (Array.isArray(ext)) { 1971 for (let e of ext) 1972 inner(e, prec); 1973 } 1974 else if (ext instanceof CompartmentInstance) { 1975 if (newCompartments.has(ext.compartment)) 1976 throw new RangeError(`Duplicate use of compartment in extensions`); 1977 let content = compartments.get(ext.compartment) || ext.inner; 1978 newCompartments.set(ext.compartment, content); 1979 inner(content, prec); 1980 } 1981 else if (ext instanceof PrecExtension) { 1982 inner(ext.inner, ext.prec); 1983 } 1984 else if (ext instanceof StateField) { 1985 result[prec].push(ext); 1986 if (ext.provides) 1987 inner(ext.provides, prec); 1988 } 1989 else if (ext instanceof FacetProvider) { 1990 result[prec].push(ext); 1991 if (ext.facet.extensions) 1992 inner(ext.facet.extensions, Prec_.default); 1993 } 1994 else { 1995 let content = ext.extension; 1996 if (!content) 1997 throw new Error(`Unrecognized extension value in extension set (${ext}). This sometimes happens because multiple instances of @codemirror/state are loaded, breaking instanceof checks.`); 1998 inner(content, prec); 1999 } 2000 } 2001 inner(extension, Prec_.default); 2002 return result.reduce((a, b) => a.concat(b)); 2003} 2004function ensureAddr(state, addr) { 2005 if (addr & 1) 2006 return 2 /* SlotStatus.Computed */; 2007 let idx = addr >> 1; 2008 let status = state.status[idx]; 2009 if (status == 4 /* SlotStatus.Computing */) 2010 throw new Error("Cyclic dependency between fields and/or facets"); 2011 if (status & 2 /* SlotStatus.Computed */) 2012 return status; 2013 state.status[idx] = 4 /* SlotStatus.Computing */; 2014 let changed = state.computeSlot(state, state.config.dynamicSlots[idx]); 2015 return state.status[idx] = 2 /* SlotStatus.Computed */ | changed; 2016} 2017function getAddr(state, addr) { 2018 return addr & 1 ? state.config.staticValues[addr >> 1] : state.values[addr >> 1]; 2019} 2020 2021const languageData = Facet.define(); 2022const allowMultipleSelections = Facet.define({ 2023 combine: values => values.some(v => v), 2024 static: true 2025}); 2026const lineSeparator = Facet.define({ 2027 combine: values => values.length ? values[0] : undefined, 2028 static: true 2029}); 2030const changeFilter = Facet.define(); 2031const transactionFilter = Facet.define(); 2032const transactionExtender = Facet.define(); 2033const readOnly = Facet.define({ 2034 combine: values => values.length ? values[0] : false 2035}); 2036 2037/** 2038Annotations are tagged values that are used to add metadata to 2039transactions in an extensible way. They should be used to model 2040things that effect the entire transaction (such as its [time 2041stamp](https://codemirror.net/6/docs/ref/#state.Transaction^time) or information about its 2042[origin](https://codemirror.net/6/docs/ref/#state.Transaction^userEvent)). For effects that happen 2043_alongside_ the other changes made by the transaction, [state 2044effects](https://codemirror.net/6/docs/ref/#state.StateEffect) are more appropriate. 2045*/ 2046class Annotation { 2047 /** 2048 @internal 2049 */ 2050 constructor( 2051 /** 2052 The annotation type. 2053 */ 2054 type, 2055 /** 2056 The value of this annotation. 2057 */ 2058 value) { 2059 this.type = type; 2060 this.value = value; 2061 } 2062 /** 2063 Define a new type of annotation. 2064 */ 2065 static define() { return new AnnotationType(); } 2066} 2067/** 2068Marker that identifies a type of [annotation](https://codemirror.net/6/docs/ref/#state.Annotation). 2069*/ 2070class AnnotationType { 2071 /** 2072 Create an instance of this annotation. 2073 */ 2074 of(value) { return new Annotation(this, value); } 2075} 2076/** 2077Representation of a type of state effect. Defined with 2078[`StateEffect.define`](https://codemirror.net/6/docs/ref/#state.StateEffect^define). 2079*/ 2080class StateEffectType { 2081 /** 2082 @internal 2083 */ 2084 constructor( 2085 // The `any` types in these function types are there to work 2086 // around TypeScript issue #37631, where the type guard on 2087 // `StateEffect.is` mysteriously stops working when these properly 2088 // have type `Value`. 2089 /** 2090 @internal 2091 */ 2092 map) { 2093 this.map = map; 2094 } 2095 /** 2096 Create a [state effect](https://codemirror.net/6/docs/ref/#state.StateEffect) instance of this 2097 type. 2098 */ 2099 of(value) { return new StateEffect(this, value); } 2100} 2101/** 2102State effects can be used to represent additional effects 2103associated with a [transaction](https://codemirror.net/6/docs/ref/#state.Transaction.effects). They 2104are often useful to model changes to custom [state 2105fields](https://codemirror.net/6/docs/ref/#state.StateField), when those changes aren't implicit in 2106document or selection changes. 2107*/ 2108class StateEffect { 2109 /** 2110 @internal 2111 */ 2112 constructor( 2113 /** 2114 @internal 2115 */ 2116 type, 2117 /** 2118 The value of this effect. 2119 */ 2120 value) { 2121 this.type = type; 2122 this.value = value; 2123 } 2124 /** 2125 Map this effect through a position mapping. Will return 2126 `undefined` when that ends up deleting the effect. 2127 */ 2128 map(mapping) { 2129 let mapped = this.type.map(this.value, mapping); 2130 return mapped === undefined ? undefined : mapped == this.value ? this : new StateEffect(this.type, mapped); 2131 } 2132 /** 2133 Tells you whether this effect object is of a given 2134 [type](https://codemirror.net/6/docs/ref/#state.StateEffectType). 2135 */ 2136 is(type) { return this.type == type; } 2137 /** 2138 Define a new effect type. The type parameter indicates the type 2139 of values that his effect holds. It should be a type that 2140 doesn't include `undefined`, since that is used in 2141 [mapping](https://codemirror.net/6/docs/ref/#state.StateEffect.map) to indicate that an effect is 2142 removed. 2143 */ 2144 static define(spec = {}) { 2145 return new StateEffectType(spec.map || (v => v)); 2146 } 2147 /** 2148 Map an array of effects through a change set. 2149 */ 2150 static mapEffects(effects, mapping) { 2151 if (!effects.length) 2152 return effects; 2153 let result = []; 2154 for (let effect of effects) { 2155 let mapped = effect.map(mapping); 2156 if (mapped) 2157 result.push(mapped); 2158 } 2159 return result; 2160 } 2161} 2162/** 2163This effect can be used to reconfigure the root extensions of 2164the editor. Doing this will discard any extensions 2165[appended](https://codemirror.net/6/docs/ref/#state.StateEffect^appendConfig), but does not reset 2166the content of [reconfigured](https://codemirror.net/6/docs/ref/#state.Compartment.reconfigure) 2167compartments. 2168*/ 2169StateEffect.reconfigure = StateEffect.define(); 2170/** 2171Append extensions to the top-level configuration of the editor. 2172*/ 2173StateEffect.appendConfig = StateEffect.define(); 2174/** 2175Changes to the editor state are grouped into transactions. 2176Typically, a user action creates a single transaction, which may 2177contain any number of document changes, may change the selection, 2178or have other effects. Create a transaction by calling 2179[`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update), or immediately 2180dispatch one by calling 2181[`EditorView.dispatch`](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch). 2182*/ 2183class Transaction { 2184 constructor( 2185 /** 2186 The state from which the transaction starts. 2187 */ 2188 startState, 2189 /** 2190 The document changes made by this transaction. 2191 */ 2192 changes, 2193 /** 2194 The selection set by this transaction, or undefined if it 2195 doesn't explicitly set a selection. 2196 */ 2197 selection, 2198 /** 2199 The effects added to the transaction. 2200 */ 2201 effects, 2202 /** 2203 @internal 2204 */ 2205 annotations, 2206 /** 2207 Whether the selection should be scrolled into view after this 2208 transaction is dispatched. 2209 */ 2210 scrollIntoView) { 2211 this.startState = startState; 2212 this.changes = changes; 2213 this.selection = selection; 2214 this.effects = effects; 2215 this.annotations = annotations; 2216 this.scrollIntoView = scrollIntoView; 2217 /** 2218 @internal 2219 */ 2220 this._doc = null; 2221 /** 2222 @internal 2223 */ 2224 this._state = null; 2225 if (selection) 2226 checkSelection(selection, changes.newLength); 2227 if (!annotations.some((a) => a.type == Transaction.time)) 2228 this.annotations = annotations.concat(Transaction.time.of(Date.now())); 2229 } 2230 /** 2231 @internal 2232 */ 2233 static create(startState, changes, selection, effects, annotations, scrollIntoView) { 2234 return new Transaction(startState, changes, selection, effects, annotations, scrollIntoView); 2235 } 2236 /** 2237 The new document produced by the transaction. Contrary to 2238 [`.state`](https://codemirror.net/6/docs/ref/#state.Transaction.state)`.doc`, accessing this won't 2239 force the entire new state to be computed right away, so it is 2240 recommended that [transaction 2241 filters](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter) use this getter 2242 when they need to look at the new document. 2243 */ 2244 get newDoc() { 2245 return this._doc || (this._doc = this.changes.apply(this.startState.doc)); 2246 } 2247 /** 2248 The new selection produced by the transaction. If 2249 [`this.selection`](https://codemirror.net/6/docs/ref/#state.Transaction.selection) is undefined, 2250 this will [map](https://codemirror.net/6/docs/ref/#state.EditorSelection.map) the start state's 2251 current selection through the changes made by the transaction. 2252 */ 2253 get newSelection() { 2254 return this.selection || this.startState.selection.map(this.changes); 2255 } 2256 /** 2257 The new state created by the transaction. Computed on demand 2258 (but retained for subsequent access), so it is recommended not to 2259 access it in [transaction 2260 filters](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter) when possible. 2261 */ 2262 get state() { 2263 if (!this._state) 2264 this.startState.applyTransaction(this); 2265 return this._state; 2266 } 2267 /** 2268 Get the value of the given annotation type, if any. 2269 */ 2270 annotation(type) { 2271 for (let ann of this.annotations) 2272 if (ann.type == type) 2273 return ann.value; 2274 return undefined; 2275 } 2276 /** 2277 Indicates whether the transaction changed the document. 2278 */ 2279 get docChanged() { return !this.changes.empty; } 2280 /** 2281 Indicates whether this transaction reconfigures the state 2282 (through a [configuration compartment](https://codemirror.net/6/docs/ref/#state.Compartment) or 2283 with a top-level configuration 2284 [effect](https://codemirror.net/6/docs/ref/#state.StateEffect^reconfigure). 2285 */ 2286 get reconfigured() { return this.startState.config != this.state.config; } 2287 /** 2288 Returns true if the transaction has a [user 2289 event](https://codemirror.net/6/docs/ref/#state.Transaction^userEvent) annotation that is equal to 2290 or more specific than `event`. For example, if the transaction 2291 has `"select.pointer"` as user event, `"select"` and 2292 `"select.pointer"` will match it. 2293 */ 2294 isUserEvent(event) { 2295 let e = this.annotation(Transaction.userEvent); 2296 return !!(e && (e == event || e.length > event.length && e.slice(0, event.length) == event && e[event.length] == ".")); 2297 } 2298} 2299/** 2300Annotation used to store transaction timestamps. Automatically 2301added to every transaction, holding `Date.now()`. 2302*/ 2303Transaction.time = Annotation.define(); 2304/** 2305Annotation used to associate a transaction with a user interface 2306event. Holds a string identifying the event, using a 2307dot-separated format to support attaching more specific 2308information. The events used by the core libraries are: 2309 2310 - `"input"` when content is entered 2311 - `"input.type"` for typed input 2312 - `"input.type.compose"` for composition 2313 - `"input.paste"` for pasted input 2314 - `"input.drop"` when adding content with drag-and-drop 2315 - `"input.complete"` when autocompleting 2316 - `"delete"` when the user deletes content 2317 - `"delete.selection"` when deleting the selection 2318 - `"delete.forward"` when deleting forward from the selection 2319 - `"delete.backward"` when deleting backward from the selection 2320 - `"delete.cut"` when cutting to the clipboard 2321 - `"move"` when content is moved 2322 - `"move.drop"` when content is moved within the editor through drag-and-drop 2323 - `"select"` when explicitly changing the selection 2324 - `"select.pointer"` when selecting with a mouse or other pointing device 2325 - `"undo"` and `"redo"` for history actions 2326 2327Use [`isUserEvent`](https://codemirror.net/6/docs/ref/#state.Transaction.isUserEvent) to check 2328whether the annotation matches a given event. 2329*/ 2330Transaction.userEvent = Annotation.define(); 2331/** 2332Annotation indicating whether a transaction should be added to 2333the undo history or not. 2334*/ 2335Transaction.addToHistory = Annotation.define(); 2336/** 2337Annotation indicating (when present and true) that a transaction 2338represents a change made by some other actor, not the user. This 2339is used, for example, to tag other people's changes in 2340collaborative editing. 2341*/ 2342Transaction.remote = Annotation.define(); 2343function joinRanges(a, b) { 2344 let result = []; 2345 for (let iA = 0, iB = 0;;) { 2346 let from, to; 2347 if (iA < a.length && (iB == b.length || b[iB] >= a[iA])) { 2348 from = a[iA++]; 2349 to = a[iA++]; 2350 } 2351 else if (iB < b.length) { 2352 from = b[iB++]; 2353 to = b[iB++]; 2354 } 2355 else 2356 return result; 2357 if (!result.length || result[result.length - 1] < from) 2358 result.push(from, to); 2359 else if (result[result.length - 1] < to) 2360 result[result.length - 1] = to; 2361 } 2362} 2363function mergeTransaction(a, b, sequential) { 2364 var _a; 2365 let mapForA, mapForB, changes; 2366 if (sequential) { 2367 mapForA = b.changes; 2368 mapForB = ChangeSet.empty(b.changes.length); 2369 changes = a.changes.compose(b.changes); 2370 } 2371 else { 2372 mapForA = b.changes.map(a.changes); 2373 mapForB = a.changes.mapDesc(b.changes, true); 2374 changes = a.changes.compose(mapForA); 2375 } 2376 return { 2377 changes, 2378 selection: b.selection ? b.selection.map(mapForB) : (_a = a.selection) === null || _a === void 0 ? void 0 : _a.map(mapForA), 2379 effects: StateEffect.mapEffects(a.effects, mapForA).concat(StateEffect.mapEffects(b.effects, mapForB)), 2380 annotations: a.annotations.length ? a.annotations.concat(b.annotations) : b.annotations, 2381 scrollIntoView: a.scrollIntoView || b.scrollIntoView 2382 }; 2383} 2384function resolveTransactionInner(state, spec, docSize) { 2385 let sel = spec.selection, annotations = asArray(spec.annotations); 2386 if (spec.userEvent) 2387 annotations = annotations.concat(Transaction.userEvent.of(spec.userEvent)); 2388 return { 2389 changes: spec.changes instanceof ChangeSet ? spec.changes 2390 : ChangeSet.of(spec.changes || [], docSize, state.facet(lineSeparator)), 2391 selection: sel && (sel instanceof EditorSelection ? sel : EditorSelection.single(sel.anchor, sel.head)), 2392 effects: asArray(spec.effects), 2393 annotations, 2394 scrollIntoView: !!spec.scrollIntoView 2395 }; 2396} 2397function resolveTransaction(state, specs, filter) { 2398 let s = resolveTransactionInner(state, specs.length ? specs[0] : {}, state.doc.length); 2399 if (specs.length && specs[0].filter === false) 2400 filter = false; 2401 for (let i = 1; i < specs.length; i++) { 2402 if (specs[i].filter === false) 2403 filter = false; 2404 let seq = !!specs[i].sequential; 2405 s = mergeTransaction(s, resolveTransactionInner(state, specs[i], seq ? s.changes.newLength : state.doc.length), seq); 2406 } 2407 let tr = Transaction.create(state, s.changes, s.selection, s.effects, s.annotations, s.scrollIntoView); 2408 return extendTransaction(filter ? filterTransaction(tr) : tr); 2409} 2410// Finish a transaction by applying filters if necessary. 2411function filterTransaction(tr) { 2412 let state = tr.startState; 2413 // Change filters 2414 let result = true; 2415 for (let filter of state.facet(changeFilter)) { 2416 let value = filter(tr); 2417 if (value === false) { 2418 result = false; 2419 break; 2420 } 2421 if (Array.isArray(value)) 2422 result = result === true ? value : joinRanges(result, value); 2423 } 2424 if (result !== true) { 2425 let changes, back; 2426 if (result === false) { 2427 back = tr.changes.invertedDesc; 2428 changes = ChangeSet.empty(state.doc.length); 2429 } 2430 else { 2431 let filtered = tr.changes.filter(result); 2432 changes = filtered.changes; 2433 back = filtered.filtered.mapDesc(filtered.changes).invertedDesc; 2434 } 2435 tr = Transaction.create(state, changes, tr.selection && tr.selection.map(back), StateEffect.mapEffects(tr.effects, back), tr.annotations, tr.scrollIntoView); 2436 } 2437 // Transaction filters 2438 let filters = state.facet(transactionFilter); 2439 for (let i = filters.length - 1; i >= 0; i--) { 2440 let filtered = filters[i](tr); 2441 if (filtered instanceof Transaction) 2442 tr = filtered; 2443 else if (Array.isArray(filtered) && filtered.length == 1 && filtered[0] instanceof Transaction) 2444 tr = filtered[0]; 2445 else 2446 tr = resolveTransaction(state, asArray(filtered), false); 2447 } 2448 return tr; 2449} 2450function extendTransaction(tr) { 2451 let state = tr.startState, extenders = state.facet(transactionExtender), spec = tr; 2452 for (let i = extenders.length - 1; i >= 0; i--) { 2453 let extension = extenders[i](tr); 2454 if (extension && Object.keys(extension).length) 2455 spec = mergeTransaction(spec, resolveTransactionInner(state, extension, tr.changes.newLength), true); 2456 } 2457 return spec == tr ? tr : Transaction.create(state, tr.changes, tr.selection, spec.effects, spec.annotations, spec.scrollIntoView); 2458} 2459const none = []; 2460function asArray(value) { 2461 return value == null ? none : Array.isArray(value) ? value : [value]; 2462} 2463 2464/** 2465The categories produced by a [character 2466categorizer](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer). These are used 2467do things like selecting by word. 2468*/ 2469exports.CharCategory = void 0; 2470(function (CharCategory) { 2471 /** 2472 Word characters. 2473 */ 2474 CharCategory[CharCategory["Word"] = 0] = "Word"; 2475 /** 2476 Whitespace. 2477 */ 2478 CharCategory[CharCategory["Space"] = 1] = "Space"; 2479 /** 2480 Anything else. 2481 */ 2482 CharCategory[CharCategory["Other"] = 2] = "Other"; 2483})(exports.CharCategory || (exports.CharCategory = {})); 2484const nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; 2485let wordChar; 2486try { 2487 wordChar = new RegExp("[\\p{Alphabetic}\\p{Number}_]", "u"); 2488} 2489catch (_) { } 2490function hasWordChar(str) { 2491 if (wordChar) 2492 return wordChar.test(str); 2493 for (let i = 0; i < str.length; i++) { 2494 let ch = str[i]; 2495 if (/\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))) 2496 return true; 2497 } 2498 return false; 2499} 2500function makeCategorizer(wordChars) { 2501 return (char) => { 2502 if (!/\S/.test(char)) 2503 return exports.CharCategory.Space; 2504 if (hasWordChar(char)) 2505 return exports.CharCategory.Word; 2506 for (let i = 0; i < wordChars.length; i++) 2507 if (char.indexOf(wordChars[i]) > -1) 2508 return exports.CharCategory.Word; 2509 return exports.CharCategory.Other; 2510 }; 2511} 2512 2513/** 2514The editor state class is a persistent (immutable) data structure. 2515To update a state, you [create](https://codemirror.net/6/docs/ref/#state.EditorState.update) a 2516[transaction](https://codemirror.net/6/docs/ref/#state.Transaction), which produces a _new_ state 2517instance, without modifying the original object. 2518 2519As such, _never_ mutate properties of a state directly. That'll 2520just break things. 2521*/ 2522class EditorState { 2523 constructor( 2524 /** 2525 @internal 2526 */ 2527 config, 2528 /** 2529 The current document. 2530 */ 2531 doc, 2532 /** 2533 The current selection. 2534 */ 2535 selection, 2536 /** 2537 @internal 2538 */ 2539 values, computeSlot, tr) { 2540 this.config = config; 2541 this.doc = doc; 2542 this.selection = selection; 2543 this.values = values; 2544 this.status = config.statusTemplate.slice(); 2545 this.computeSlot = computeSlot; 2546 // Fill in the computed state immediately, so that further queries 2547 // for it made during the update return this state 2548 if (tr) 2549 tr._state = this; 2550 for (let i = 0; i < this.config.dynamicSlots.length; i++) 2551 ensureAddr(this, i << 1); 2552 this.computeSlot = null; 2553 } 2554 field(field, require = true) { 2555 let addr = this.config.address[field.id]; 2556 if (addr == null) { 2557 if (require) 2558 throw new RangeError("Field is not present in this state"); 2559 return undefined; 2560 } 2561 ensureAddr(this, addr); 2562 return getAddr(this, addr); 2563 } 2564 /** 2565 Create a [transaction](https://codemirror.net/6/docs/ref/#state.Transaction) that updates this 2566 state. Any number of [transaction specs](https://codemirror.net/6/docs/ref/#state.TransactionSpec) 2567 can be passed. Unless 2568 [`sequential`](https://codemirror.net/6/docs/ref/#state.TransactionSpec.sequential) is set, the 2569 [changes](https://codemirror.net/6/docs/ref/#state.TransactionSpec.changes) (if any) of each spec 2570 are assumed to start in the _current_ document (not the document 2571 produced by previous specs), and its 2572 [selection](https://codemirror.net/6/docs/ref/#state.TransactionSpec.selection) and 2573 [effects](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) are assumed to refer 2574 to the document created by its _own_ changes. The resulting 2575 transaction contains the combined effect of all the different 2576 specs. For [selection](https://codemirror.net/6/docs/ref/#state.TransactionSpec.selection), later 2577 specs take precedence over earlier ones. 2578 */ 2579 update(...specs) { 2580 return resolveTransaction(this, specs, true); 2581 } 2582 /** 2583 @internal 2584 */ 2585 applyTransaction(tr) { 2586 let conf = this.config, { base, compartments } = conf; 2587 for (let effect of tr.effects) { 2588 if (effect.is(Compartment.reconfigure)) { 2589 if (conf) { 2590 compartments = new Map; 2591 conf.compartments.forEach((val, key) => compartments.set(key, val)); 2592 conf = null; 2593 } 2594 compartments.set(effect.value.compartment, effect.value.extension); 2595 } 2596 else if (effect.is(StateEffect.reconfigure)) { 2597 conf = null; 2598 base = effect.value; 2599 } 2600 else if (effect.is(StateEffect.appendConfig)) { 2601 conf = null; 2602 base = asArray(base).concat(effect.value); 2603 } 2604 } 2605 let startValues; 2606 if (!conf) { 2607 conf = Configuration.resolve(base, compartments, this); 2608 let intermediateState = new EditorState(conf, this.doc, this.selection, conf.dynamicSlots.map(() => null), (state, slot) => slot.reconfigure(state, this), null); 2609 startValues = intermediateState.values; 2610 } 2611 else { 2612 startValues = tr.startState.values.slice(); 2613 } 2614 let selection = tr.startState.facet(allowMultipleSelections) ? tr.newSelection : tr.newSelection.asSingle(); 2615 new EditorState(conf, tr.newDoc, selection, startValues, (state, slot) => slot.update(state, tr), tr); 2616 } 2617 /** 2618 Create a [transaction spec](https://codemirror.net/6/docs/ref/#state.TransactionSpec) that 2619 replaces every selection range with the given content. 2620 */ 2621 replaceSelection(text) { 2622 if (typeof text == "string") 2623 text = this.toText(text); 2624 return this.changeByRange(range => ({ changes: { from: range.from, to: range.to, insert: text }, 2625 range: EditorSelection.cursor(range.from + text.length) })); 2626 } 2627 /** 2628 Create a set of changes and a new selection by running the given 2629 function for each range in the active selection. The function 2630 can return an optional set of changes (in the coordinate space 2631 of the start document), plus an updated range (in the coordinate 2632 space of the document produced by the call's own changes). This 2633 method will merge all the changes and ranges into a single 2634 changeset and selection, and return it as a [transaction 2635 spec](https://codemirror.net/6/docs/ref/#state.TransactionSpec), which can be passed to 2636 [`update`](https://codemirror.net/6/docs/ref/#state.EditorState.update). 2637 */ 2638 changeByRange(f) { 2639 let sel = this.selection; 2640 let result1 = f(sel.ranges[0]); 2641 let changes = this.changes(result1.changes), ranges = [result1.range]; 2642 let effects = asArray(result1.effects); 2643 for (let i = 1; i < sel.ranges.length; i++) { 2644 let result = f(sel.ranges[i]); 2645 let newChanges = this.changes(result.changes), newMapped = newChanges.map(changes); 2646 for (let j = 0; j < i; j++) 2647 ranges[j] = ranges[j].map(newMapped); 2648 let mapBy = changes.mapDesc(newChanges, true); 2649 ranges.push(result.range.map(mapBy)); 2650 changes = changes.compose(newMapped); 2651 effects = StateEffect.mapEffects(effects, newMapped).concat(StateEffect.mapEffects(asArray(result.effects), mapBy)); 2652 } 2653 return { 2654 changes, 2655 selection: EditorSelection.create(ranges, sel.mainIndex), 2656 effects 2657 }; 2658 } 2659 /** 2660 Create a [change set](https://codemirror.net/6/docs/ref/#state.ChangeSet) from the given change 2661 description, taking the state's document length and line 2662 separator into account. 2663 */ 2664 changes(spec = []) { 2665 if (spec instanceof ChangeSet) 2666 return spec; 2667 return ChangeSet.of(spec, this.doc.length, this.facet(EditorState.lineSeparator)); 2668 } 2669 /** 2670 Using the state's [line 2671 separator](https://codemirror.net/6/docs/ref/#state.EditorState^lineSeparator), create a 2672 [`Text`](https://codemirror.net/6/docs/ref/#state.Text) instance from the given string. 2673 */ 2674 toText(string) { 2675 return Text.of(string.split(this.facet(EditorState.lineSeparator) || DefaultSplit)); 2676 } 2677 /** 2678 Return the given range of the document as a string. 2679 */ 2680 sliceDoc(from = 0, to = this.doc.length) { 2681 return this.doc.sliceString(from, to, this.lineBreak); 2682 } 2683 /** 2684 Get the value of a state [facet](https://codemirror.net/6/docs/ref/#state.Facet). 2685 */ 2686 facet(facet) { 2687 let addr = this.config.address[facet.id]; 2688 if (addr == null) 2689 return facet.default; 2690 ensureAddr(this, addr); 2691 return getAddr(this, addr); 2692 } 2693 /** 2694 Convert this state to a JSON-serializable object. When custom 2695 fields should be serialized, you can pass them in as an object 2696 mapping property names (in the resulting object, which should 2697 not use `doc` or `selection`) to fields. 2698 */ 2699 toJSON(fields) { 2700 let result = { 2701 doc: this.sliceDoc(), 2702 selection: this.selection.toJSON() 2703 }; 2704 if (fields) 2705 for (let prop in fields) { 2706 let value = fields[prop]; 2707 if (value instanceof StateField && this.config.address[value.id] != null) 2708 result[prop] = value.spec.toJSON(this.field(fields[prop]), this); 2709 } 2710 return result; 2711 } 2712 /** 2713 Deserialize a state from its JSON representation. When custom 2714 fields should be deserialized, pass the same object you passed 2715 to [`toJSON`](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) when serializing as 2716 third argument. 2717 */ 2718 static fromJSON(json, config = {}, fields) { 2719 if (!json || typeof json.doc != "string") 2720 throw new RangeError("Invalid JSON representation for EditorState"); 2721 let fieldInit = []; 2722 if (fields) 2723 for (let prop in fields) { 2724 if (Object.prototype.hasOwnProperty.call(json, prop)) { 2725 let field = fields[prop], value = json[prop]; 2726 fieldInit.push(field.init(state => field.spec.fromJSON(value, state))); 2727 } 2728 } 2729 return EditorState.create({ 2730 doc: json.doc, 2731 selection: EditorSelection.fromJSON(json.selection), 2732 extensions: config.extensions ? fieldInit.concat([config.extensions]) : fieldInit 2733 }); 2734 } 2735 /** 2736 Create a new state. You'll usually only need this when 2737 initializing an editor—updated states are created by applying 2738 transactions. 2739 */ 2740 static create(config = {}) { 2741 let configuration = Configuration.resolve(config.extensions || [], new Map); 2742 let doc = config.doc instanceof Text ? config.doc 2743 : Text.of((config.doc || "").split(configuration.staticFacet(EditorState.lineSeparator) || DefaultSplit)); 2744 let selection = !config.selection ? EditorSelection.single(0) 2745 : config.selection instanceof EditorSelection ? config.selection 2746 : EditorSelection.single(config.selection.anchor, config.selection.head); 2747 checkSelection(selection, doc.length); 2748 if (!configuration.staticFacet(allowMultipleSelections)) 2749 selection = selection.asSingle(); 2750 return new EditorState(configuration, doc, selection, configuration.dynamicSlots.map(() => null), (state, slot) => slot.create(state), null); 2751 } 2752 /** 2753 The size (in columns) of a tab in the document, determined by 2754 the [`tabSize`](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize) facet. 2755 */ 2756 get tabSize() { return this.facet(EditorState.tabSize); } 2757 /** 2758 Get the proper [line-break](https://codemirror.net/6/docs/ref/#state.EditorState^lineSeparator) 2759 string for this state. 2760 */ 2761 get lineBreak() { return this.facet(EditorState.lineSeparator) || "\n"; } 2762 /** 2763 Returns true when the editor is 2764 [configured](https://codemirror.net/6/docs/ref/#state.EditorState^readOnly) to be read-only. 2765 */ 2766 get readOnly() { return this.facet(readOnly); } 2767 /** 2768 Look up a translation for the given phrase (via the 2769 [`phrases`](https://codemirror.net/6/docs/ref/#state.EditorState^phrases) facet), or return the 2770 original string if no translation is found. 2771 2772 If additional arguments are passed, they will be inserted in 2773 place of markers like `$1` (for the first value) and `$2`, etc. 2774 A single `$` is equivalent to `$1`, and `$$` will produce a 2775 literal dollar sign. 2776 */ 2777 phrase(phrase, ...insert) { 2778 for (let map of this.facet(EditorState.phrases)) 2779 if (Object.prototype.hasOwnProperty.call(map, phrase)) { 2780 phrase = map[phrase]; 2781 break; 2782 } 2783 if (insert.length) 2784 phrase = phrase.replace(/\$(\$|\d*)/g, (m, i) => { 2785 if (i == "$") 2786 return "$"; 2787 let n = +(i || 1); 2788 return !n || n > insert.length ? m : insert[n - 1]; 2789 }); 2790 return phrase; 2791 } 2792 /** 2793 Find the values for a given language data field, provided by the 2794 the [`languageData`](https://codemirror.net/6/docs/ref/#state.EditorState^languageData) facet. 2795 2796 Examples of language data fields are... 2797 2798 - [`"commentTokens"`](https://codemirror.net/6/docs/ref/#commands.CommentTokens) for specifying 2799 comment syntax. 2800 - [`"autocomplete"`](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion^config.override) 2801 for providing language-specific completion sources. 2802 - [`"wordChars"`](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer) for adding 2803 characters that should be considered part of words in this 2804 language. 2805 - [`"closeBrackets"`](https://codemirror.net/6/docs/ref/#autocomplete.CloseBracketConfig) controls 2806 bracket closing behavior. 2807 */ 2808 languageDataAt(name, pos, side = -1) { 2809 let values = []; 2810 for (let provider of this.facet(languageData)) { 2811 for (let result of provider(this, pos, side)) { 2812 if (Object.prototype.hasOwnProperty.call(result, name)) 2813 values.push(result[name]); 2814 } 2815 } 2816 return values; 2817 } 2818 /** 2819 Return a function that can categorize strings (expected to 2820 represent a single [grapheme cluster](https://codemirror.net/6/docs/ref/#state.findClusterBreak)) 2821 into one of: 2822 2823 - Word (contains an alphanumeric character or a character 2824 explicitly listed in the local language's `"wordChars"` 2825 language data, which should be a string) 2826 - Space (contains only whitespace) 2827 - Other (anything else) 2828 */ 2829 charCategorizer(at) { 2830 let chars = this.languageDataAt("wordChars", at); 2831 return makeCategorizer(chars.length ? chars[0] : ""); 2832 } 2833 /** 2834 Find the word at the given position, meaning the range 2835 containing all [word](https://codemirror.net/6/docs/ref/#state.CharCategory.Word) characters 2836 around it. If no word characters are adjacent to the position, 2837 this returns null. 2838 */ 2839 wordAt(pos) { 2840 let { text, from, length } = this.doc.lineAt(pos); 2841 let cat = this.charCategorizer(pos); 2842 let start = pos - from, end = pos - from; 2843 while (start > 0) { 2844 let prev = findClusterBreak(text, start, false); 2845 if (cat(text.slice(prev, start)) != exports.CharCategory.Word) 2846 break; 2847 start = prev; 2848 } 2849 while (end < length) { 2850 let next = findClusterBreak(text, end); 2851 if (cat(text.slice(end, next)) != exports.CharCategory.Word) 2852 break; 2853 end = next; 2854 } 2855 return start == end ? null : EditorSelection.range(start + from, end + from); 2856 } 2857} 2858/** 2859A facet that, when enabled, causes the editor to allow multiple 2860ranges to be selected. Be careful though, because by default the 2861editor relies on the native DOM selection, which cannot handle 2862multiple selections. An extension like 2863[`drawSelection`](https://codemirror.net/6/docs/ref/#view.drawSelection) can be used to make 2864secondary selections visible to the user. 2865*/ 2866EditorState.allowMultipleSelections = allowMultipleSelections; 2867/** 2868Configures the tab size to use in this state. The first 2869(highest-precedence) value of the facet is used. If no value is 2870given, this defaults to 4. 2871*/ 2872EditorState.tabSize = Facet.define({ 2873 combine: values => values.length ? values[0] : 4 2874}); 2875/** 2876The line separator to use. By default, any of `"\n"`, `"\r\n"` 2877and `"\r"` is treated as a separator when splitting lines, and 2878lines are joined with `"\n"`. 2879 2880When you configure a value here, only that precise separator 2881will be used, allowing you to round-trip documents through the 2882editor without normalizing line separators. 2883*/ 2884EditorState.lineSeparator = lineSeparator; 2885/** 2886This facet controls the value of the 2887[`readOnly`](https://codemirror.net/6/docs/ref/#state.EditorState.readOnly) getter, which is 2888consulted by commands and extensions that implement editing 2889functionality to determine whether they should apply. It 2890defaults to false, but when its highest-precedence value is 2891`true`, such functionality disables itself. 2892 2893Not to be confused with 2894[`EditorView.editable`](https://codemirror.net/6/docs/ref/#view.EditorView^editable), which 2895controls whether the editor's DOM is set to be editable (and 2896thus focusable). 2897*/ 2898EditorState.readOnly = readOnly; 2899/** 2900Registers translation phrases. The 2901[`phrase`](https://codemirror.net/6/docs/ref/#state.EditorState.phrase) method will look through 2902all objects registered with this facet to find translations for 2903its argument. 2904*/ 2905EditorState.phrases = Facet.define({ 2906 compare(a, b) { 2907 let kA = Object.keys(a), kB = Object.keys(b); 2908 return kA.length == kB.length && kA.every(k => a[k] == b[k]); 2909 } 2910}); 2911/** 2912A facet used to register [language 2913data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) providers. 2914*/ 2915EditorState.languageData = languageData; 2916/** 2917Facet used to register change filters, which are called for each 2918transaction (unless explicitly 2919[disabled](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter)), and can suppress 2920part of the transaction's changes. 2921 2922Such a function can return `true` to indicate that it doesn't 2923want to do anything, `false` to completely stop the changes in 2924the transaction, or a set of ranges in which changes should be 2925suppressed. Such ranges are represented as an array of numbers, 2926with each pair of two numbers indicating the start and end of a 2927range. So for example `[10, 20, 100, 110]` suppresses changes 2928between 10 and 20, and between 100 and 110. 2929*/ 2930EditorState.changeFilter = changeFilter; 2931/** 2932Facet used to register a hook that gets a chance to update or 2933replace transaction specs before they are applied. This will 2934only be applied for transactions that don't have 2935[`filter`](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter) set to `false`. You 2936can either return a single transaction spec (possibly the input 2937transaction), or an array of specs (which will be combined in 2938the same way as the arguments to 2939[`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update)). 2940 2941When possible, it is recommended to avoid accessing 2942[`Transaction.state`](https://codemirror.net/6/docs/ref/#state.Transaction.state) in a filter, 2943since it will force creation of a state that will then be 2944discarded again, if the transaction is actually filtered. 2945 2946(This functionality should be used with care. Indiscriminately 2947modifying transaction is likely to break something or degrade 2948the user experience.) 2949*/ 2950EditorState.transactionFilter = transactionFilter; 2951/** 2952This is a more limited form of 2953[`transactionFilter`](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter), 2954which can only add 2955[annotations](https://codemirror.net/6/docs/ref/#state.TransactionSpec.annotations) and 2956[effects](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects). _But_, this type 2957of filter runs even if the transaction has disabled regular 2958[filtering](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter), making it suitable 2959for effects that don't need to touch the changes or selection, 2960but do want to process every transaction. 2961 2962Extenders run _after_ filters, when both are present. 2963*/ 2964EditorState.transactionExtender = transactionExtender; 2965Compartment.reconfigure = StateEffect.define(); 2966 2967/** 2968Utility function for combining behaviors to fill in a config 2969object from an array of provided configs. `defaults` should hold 2970default values for all optional fields in `Config`. 2971 2972The function will, by default, error 2973when a field gets two values that aren't `===`-equal, but you can 2974provide combine functions per field to do something else. 2975*/ 2976function combineConfig(configs, defaults, // Should hold only the optional properties of Config, but I haven't managed to express that 2977combine = {}) { 2978 let result = {}; 2979 for (let config of configs) 2980 for (let key of Object.keys(config)) { 2981 let value = config[key], current = result[key]; 2982 if (current === undefined) 2983 result[key] = value; 2984 else if (current === value || value === undefined) ; // No conflict 2985 else if (Object.hasOwnProperty.call(combine, key)) 2986 result[key] = combine[key](current, value); 2987 else 2988 throw new Error("Config merge conflict for field " + key); 2989 } 2990 for (let key in defaults) 2991 if (result[key] === undefined) 2992 result[key] = defaults[key]; 2993 return result; 2994} 2995 2996/** 2997Each range is associated with a value, which must inherit from 2998this class. 2999*/ 3000class RangeValue { 3001 /** 3002 Compare this value with another value. Used when comparing 3003 rangesets. The default implementation compares by identity. 3004 Unless you are only creating a fixed number of unique instances 3005 of your value type, it is a good idea to implement this 3006 properly. 3007 */ 3008 eq(other) { return this == other; } 3009 /** 3010 Create a [range](https://codemirror.net/6/docs/ref/#state.Range) with this value. 3011 */ 3012 range(from, to = from) { return Range.create(from, to, this); } 3013} 3014RangeValue.prototype.startSide = RangeValue.prototype.endSide = 0; 3015RangeValue.prototype.point = false; 3016RangeValue.prototype.mapMode = exports.MapMode.TrackDel; 3017function cmpVal(a, b) { 3018 return a == b || a.constructor == b.constructor && a.eq(b); 3019} 3020/** 3021A range associates a value with a range of positions. 3022*/ 3023class Range { 3024 constructor( 3025 /** 3026 The range's start position. 3027 */ 3028 from, 3029 /** 3030 Its end position. 3031 */ 3032 to, 3033 /** 3034 The value associated with this range. 3035 */ 3036 value) { 3037 this.from = from; 3038 this.to = to; 3039 this.value = value; 3040 } 3041 /** 3042 @internal 3043 */ 3044 static create(from, to, value) { 3045 return new Range(from, to, value); 3046 } 3047} 3048function cmpRange(a, b) { 3049 return a.from - b.from || a.value.startSide - b.value.startSide; 3050} 3051class Chunk { 3052 constructor(from, to, value, 3053 // Chunks are marked with the largest point that occurs 3054 // in them (or -1 for no points), so that scans that are 3055 // only interested in points (such as the 3056 // heightmap-related logic) can skip range-only chunks. 3057 maxPoint) { 3058 this.from = from; 3059 this.to = to; 3060 this.value = value; 3061 this.maxPoint = maxPoint; 3062 } 3063 get length() { return this.to[this.to.length - 1]; } 3064 // Find the index of the given position and side. Use the ranges' 3065 // `from` pos when `end == false`, `to` when `end == true`. 3066 findIndex(pos, side, end, startAt = 0) { 3067 let arr = end ? this.to : this.from; 3068 for (let lo = startAt, hi = arr.length;;) { 3069 if (lo == hi) 3070 return lo; 3071 let mid = (lo + hi) >> 1; 3072 let diff = arr[mid] - pos || (end ? this.value[mid].endSide : this.value[mid].startSide) - side; 3073 if (mid == lo) 3074 return diff >= 0 ? lo : hi; 3075 if (diff >= 0) 3076 hi = mid; 3077 else 3078 lo = mid + 1; 3079 } 3080 } 3081 between(offset, from, to, f) { 3082 for (let i = this.findIndex(from, -1000000000 /* C.Far */, true), e = this.findIndex(to, 1000000000 /* C.Far */, false, i); i < e; i++) 3083 if (f(this.from[i] + offset, this.to[i] + offset, this.value[i]) === false) 3084 return false; 3085 } 3086 map(offset, changes) { 3087 let value = [], from = [], to = [], newPos = -1, maxPoint = -1; 3088 for (let i = 0; i < this.value.length; i++) { 3089 let val = this.value[i], curFrom = this.from[i] + offset, curTo = this.to[i] + offset, newFrom, newTo; 3090 if (curFrom == curTo) { 3091 let mapped = changes.mapPos(curFrom, val.startSide, val.mapMode); 3092 if (mapped == null) 3093 continue; 3094 newFrom = newTo = mapped; 3095 if (val.startSide != val.endSide) { 3096 newTo = changes.mapPos(curFrom, val.endSide); 3097 if (newTo < newFrom) 3098 continue; 3099 } 3100 } 3101 else { 3102 newFrom = changes.mapPos(curFrom, val.startSide); 3103 newTo = changes.mapPos(curTo, val.endSide); 3104 if (newFrom > newTo || newFrom == newTo && val.startSide > 0 && val.endSide <= 0) 3105 continue; 3106 } 3107 if ((newTo - newFrom || val.endSide - val.startSide) < 0) 3108 continue; 3109 if (newPos < 0) 3110 newPos = newFrom; 3111 if (val.point) 3112 maxPoint = Math.max(maxPoint, newTo - newFrom); 3113 value.push(val); 3114 from.push(newFrom - newPos); 3115 to.push(newTo - newPos); 3116 } 3117 return { mapped: value.length ? new Chunk(from, to, value, maxPoint) : null, pos: newPos }; 3118 } 3119} 3120/** 3121A range set stores a collection of [ranges](https://codemirror.net/6/docs/ref/#state.Range) in a 3122way that makes them efficient to [map](https://codemirror.net/6/docs/ref/#state.RangeSet.map) and 3123[update](https://codemirror.net/6/docs/ref/#state.RangeSet.update). This is an immutable data 3124structure. 3125*/ 3126class RangeSet { 3127 constructor( 3128 /** 3129 @internal 3130 */ 3131 chunkPos, 3132 /** 3133 @internal 3134 */ 3135 chunk, 3136 /** 3137 @internal 3138 */ 3139 nextLayer, 3140 /** 3141 @internal 3142 */ 3143 maxPoint) { 3144 this.chunkPos = chunkPos; 3145 this.chunk = chunk; 3146 this.nextLayer = nextLayer; 3147 this.maxPoint = maxPoint; 3148 } 3149 /** 3150 @internal 3151 */ 3152 static create(chunkPos, chunk, nextLayer, maxPoint) { 3153 return new RangeSet(chunkPos, chunk, nextLayer, maxPoint); 3154 } 3155 /** 3156 @internal 3157 */ 3158 get length() { 3159 let last = this.chunk.length - 1; 3160 return last < 0 ? 0 : Math.max(this.chunkEnd(last), this.nextLayer.length); 3161 } 3162 /** 3163 The number of ranges in the set. 3164 */ 3165 get size() { 3166 if (this.isEmpty) 3167 return 0; 3168 let size = this.nextLayer.size; 3169 for (let chunk of this.chunk) 3170 size += chunk.value.length; 3171 return size; 3172 } 3173 /** 3174 @internal 3175 */ 3176 chunkEnd(index) { 3177 return this.chunkPos[index] + this.chunk[index].length; 3178 } 3179 /** 3180 Update the range set, optionally adding new ranges or filtering 3181 out existing ones. 3182 3183 (Note: The type parameter is just there as a kludge to work 3184 around TypeScript variance issues that prevented `RangeSet<X>` 3185 from being a subtype of `RangeSet<Y>` when `X` is a subtype of 3186 `Y`.) 3187 */ 3188 update(updateSpec) { 3189 let { add = [], sort = false, filterFrom = 0, filterTo = this.length } = updateSpec; 3190 let filter = updateSpec.filter; 3191 if (add.length == 0 && !filter) 3192 return this; 3193 if (sort) 3194 add = add.slice().sort(cmpRange); 3195 if (this.isEmpty) 3196 return add.length ? RangeSet.of(add) : this; 3197 let cur = new LayerCursor(this, null, -1).goto(0), i = 0, spill = []; 3198 let builder = new RangeSetBuilder(); 3199 while (cur.value || i < add.length) { 3200 if (i < add.length && (cur.from - add[i].from || cur.startSide - add[i].value.startSide) >= 0) { 3201 let range = add[i++]; 3202 if (!builder.addInner(range.from, range.to, range.value)) 3203 spill.push(range); 3204 } 3205 else if (cur.rangeIndex == 1 && cur.chunkIndex < this.chunk.length && 3206 (i == add.length || this.chunkEnd(cur.chunkIndex) < add[i].from) && 3207 (!filter || filterFrom > this.chunkEnd(cur.chunkIndex) || filterTo < this.chunkPos[cur.chunkIndex]) && 3208 builder.addChunk(this.chunkPos[cur.chunkIndex], this.chunk[cur.chunkIndex])) { 3209 cur.nextChunk(); 3210 } 3211 else { 3212 if (!filter || filterFrom > cur.to || filterTo < cur.from || filter(cur.from, cur.to, cur.value)) { 3213 if (!builder.addInner(cur.from, cur.to, cur.value)) 3214 spill.push(Range.create(cur.from, cur.to, cur.value)); 3215 } 3216 cur.next(); 3217 } 3218 } 3219 return builder.finishInner(this.nextLayer.isEmpty && !spill.length ? RangeSet.empty 3220 : this.nextLayer.update({ add: spill, filter, filterFrom, filterTo })); 3221 } 3222 /** 3223 Map this range set through a set of changes, return the new set. 3224 */ 3225 map(changes) { 3226 if (changes.empty || this.isEmpty) 3227 return this; 3228 let chunks = [], chunkPos = [], maxPoint = -1; 3229 for (let i = 0; i < this.chunk.length; i++) { 3230 let start = this.chunkPos[i], chunk = this.chunk[i]; 3231 let touch = changes.touchesRange(start, start + chunk.length); 3232 if (touch === false) { 3233 maxPoint = Math.max(maxPoint, chunk.maxPoint); 3234 chunks.push(chunk); 3235 chunkPos.push(changes.mapPos(start)); 3236 } 3237 else if (touch === true) { 3238 let { mapped, pos } = chunk.map(start, changes); 3239 if (mapped) { 3240 maxPoint = Math.max(maxPoint, mapped.maxPoint); 3241 chunks.push(mapped); 3242 chunkPos.push(pos); 3243 } 3244 } 3245 } 3246 let next = this.nextLayer.map(changes); 3247 return chunks.length == 0 ? next : new RangeSet(chunkPos, chunks, next || RangeSet.empty, maxPoint); 3248 } 3249 /** 3250 Iterate over the ranges that touch the region `from` to `to`, 3251 calling `f` for each. There is no guarantee that the ranges will 3252 be reported in any specific order. When the callback returns 3253 `false`, iteration stops. 3254 */ 3255 between(from, to, f) { 3256 if (this.isEmpty) 3257 return; 3258 for (let i = 0; i < this.chunk.length; i++) { 3259 let start = this.chunkPos[i], chunk = this.chunk[i]; 3260 if (to >= start && from <= start + chunk.length && 3261 chunk.between(start, from - start, to - start, f) === false) 3262 return; 3263 } 3264 this.nextLayer.between(from, to, f); 3265 } 3266 /** 3267 Iterate over the ranges in this set, in order, including all 3268 ranges that end at or after `from`. 3269 */ 3270 iter(from = 0) { 3271 return HeapCursor.from([this]).goto(from); 3272 } 3273 /** 3274 @internal 3275 */ 3276 get isEmpty() { return this.nextLayer == this; } 3277 /** 3278 Iterate over the ranges in a collection of sets, in order, 3279 starting from `from`. 3280 */ 3281 static iter(sets, from = 0) { 3282 return HeapCursor.from(sets).goto(from); 3283 } 3284 /** 3285 Iterate over two groups of sets, calling methods on `comparator` 3286 to notify it of possible differences. 3287 */ 3288 static compare(oldSets, newSets, 3289 /** 3290 This indicates how the underlying data changed between these 3291 ranges, and is needed to synchronize the iteration. 3292 */ 3293 textDiff, comparator, 3294 /** 3295 Can be used to ignore all non-point ranges, and points below 3296 the given size. When -1, all ranges are compared. 3297 */ 3298 minPointSize = -1) { 3299 let a = oldSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize); 3300 let b = newSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize); 3301 let sharedChunks = findSharedChunks(a, b, textDiff); 3302 let sideA = new SpanCursor(a, sharedChunks, minPointSize); 3303 let sideB = new SpanCursor(b, sharedChunks, minPointSize); 3304 textDiff.iterGaps((fromA, fromB, length) => compare(sideA, fromA, sideB, fromB, length, comparator)); 3305 if (textDiff.empty && textDiff.length == 0) 3306 compare(sideA, 0, sideB, 0, 0, comparator); 3307 } 3308 /** 3309 Compare the contents of two groups of range sets, returning true 3310 if they are equivalent in the given range. 3311 */ 3312 static eq(oldSets, newSets, from = 0, to) { 3313 if (to == null) 3314 to = 1000000000 /* C.Far */ - 1; 3315 let a = oldSets.filter(set => !set.isEmpty && newSets.indexOf(set) < 0); 3316 let b = newSets.filter(set => !set.isEmpty && oldSets.indexOf(set) < 0); 3317 if (a.length != b.length) 3318 return false; 3319 if (!a.length) 3320 return true; 3321 let sharedChunks = findSharedChunks(a, b); 3322 let sideA = new SpanCursor(a, sharedChunks, 0).goto(from), sideB = new SpanCursor(b, sharedChunks, 0).goto(from); 3323 for (;;) { 3324 if (sideA.to != sideB.to || 3325 !sameValues(sideA.active, sideB.active) || 3326 sideA.point && (!sideB.point || !cmpVal(sideA.point, sideB.point))) 3327 return false; 3328 if (sideA.to > to) 3329 return true; 3330 sideA.next(); 3331 sideB.next(); 3332 } 3333 } 3334 /** 3335 Iterate over a group of range sets at the same time, notifying 3336 the iterator about the ranges covering every given piece of 3337 content. Returns the open count (see 3338 [`SpanIterator.span`](https://codemirror.net/6/docs/ref/#state.SpanIterator.span)) at the end 3339 of the iteration. 3340 */ 3341 static spans(sets, from, to, iterator, 3342 /** 3343 When given and greater than -1, only points of at least this 3344 size are taken into account. 3345 */ 3346 minPointSize = -1) { 3347 let cursor = new SpanCursor(sets, null, minPointSize).goto(from), pos = from; 3348 let openRanges = cursor.openStart; 3349 for (;;) { 3350 let curTo = Math.min(cursor.to, to); 3351 if (cursor.point) { 3352 let active = cursor.activeForPoint(cursor.to); 3353 let openCount = cursor.pointFrom < from ? active.length + 1 3354 : cursor.point.startSide < 0 ? active.length 3355 : Math.min(active.length, openRanges); 3356 iterator.point(pos, curTo, cursor.point, active, openCount, cursor.pointRank); 3357 openRanges = Math.min(cursor.openEnd(curTo), active.length); 3358 } 3359 else if (curTo > pos) { 3360 iterator.span(pos, curTo, cursor.active, openRanges); 3361 openRanges = cursor.openEnd(curTo); 3362 } 3363 if (cursor.to > to) 3364 return openRanges + (cursor.point && cursor.to > to ? 1 : 0); 3365 pos = cursor.to; 3366 cursor.next(); 3367 } 3368 } 3369 /** 3370 Create a range set for the given range or array of ranges. By 3371 default, this expects the ranges to be _sorted_ (by start 3372 position and, if two start at the same position, 3373 `value.startSide`). You can pass `true` as second argument to 3374 cause the method to sort them. 3375 */ 3376 static of(ranges, sort = false) { 3377 let build = new RangeSetBuilder(); 3378 for (let range of ranges instanceof Range ? [ranges] : sort ? lazySort(ranges) : ranges) 3379 build.add(range.from, range.to, range.value); 3380 return build.finish(); 3381 } 3382 /** 3383 Join an array of range sets into a single set. 3384 */ 3385 static join(sets) { 3386 if (!sets.length) 3387 return RangeSet.empty; 3388 let result = sets[sets.length - 1]; 3389 for (let i = sets.length - 2; i >= 0; i--) { 3390 for (let layer = sets[i]; layer != RangeSet.empty; layer = layer.nextLayer) 3391 result = new RangeSet(layer.chunkPos, layer.chunk, result, Math.max(layer.maxPoint, result.maxPoint)); 3392 } 3393 return result; 3394 } 3395} 3396/** 3397The empty set of ranges. 3398*/ 3399RangeSet.empty = new RangeSet([], [], null, -1); 3400function lazySort(ranges) { 3401 if (ranges.length > 1) 3402 for (let prev = ranges[0], i = 1; i < ranges.length; i++) { 3403 let cur = ranges[i]; 3404 if (cmpRange(prev, cur) > 0) 3405 return ranges.slice().sort(cmpRange); 3406 prev = cur; 3407 } 3408 return ranges; 3409} 3410RangeSet.empty.nextLayer = RangeSet.empty; 3411/** 3412A range set builder is a data structure that helps build up a 3413[range set](https://codemirror.net/6/docs/ref/#state.RangeSet) directly, without first allocating 3414an array of [`Range`](https://codemirror.net/6/docs/ref/#state.Range) objects. 3415*/ 3416class RangeSetBuilder { 3417 finishChunk(newArrays) { 3418 this.chunks.push(new Chunk(this.from, this.to, this.value, this.maxPoint)); 3419 this.chunkPos.push(this.chunkStart); 3420 this.chunkStart = -1; 3421 this.setMaxPoint = Math.max(this.setMaxPoint, this.maxPoint); 3422 this.maxPoint = -1; 3423 if (newArrays) { 3424 this.from = []; 3425 this.to = []; 3426 this.value = []; 3427 } 3428 } 3429 /** 3430 Create an empty builder. 3431 */ 3432 constructor() { 3433 this.chunks = []; 3434 this.chunkPos = []; 3435 this.chunkStart = -1; 3436 this.last = null; 3437 this.lastFrom = -1000000000 /* C.Far */; 3438 this.lastTo = -1000000000 /* C.Far */; 3439 this.from = []; 3440 this.to = []; 3441 this.value = []; 3442 this.maxPoint = -1; 3443 this.setMaxPoint = -1; 3444 this.nextLayer = null; 3445 } 3446 /** 3447 Add a range. Ranges should be added in sorted (by `from` and 3448 `value.startSide`) order. 3449 */ 3450 add(from, to, value) { 3451 if (!this.addInner(from, to, value)) 3452 (this.nextLayer || (this.nextLayer = new RangeSetBuilder)).add(from, to, value); 3453 } 3454 /** 3455 @internal 3456 */ 3457 addInner(from, to, value) { 3458 let diff = from - this.lastTo || value.startSide - this.last.endSide; 3459 if (diff <= 0 && (from - this.lastFrom || value.startSide - this.last.startSide) < 0) 3460 throw new Error("Ranges must be added sorted by `from` position and `startSide`"); 3461 if (diff < 0) 3462 return false; 3463 if (this.from.length == 250 /* C.ChunkSize */) 3464 this.finishChunk(true); 3465 if (this.chunkStart < 0) 3466 this.chunkStart = from; 3467 this.from.push(from - this.chunkStart); 3468 this.to.push(to - this.chunkStart); 3469 this.last = value; 3470 this.lastFrom = from; 3471 this.lastTo = to; 3472 this.value.push(value); 3473 if (value.point) 3474 this.maxPoint = Math.max(this.maxPoint, to - from); 3475 return true; 3476 } 3477 /** 3478 @internal 3479 */ 3480 addChunk(from, chunk) { 3481 if ((from - this.lastTo || chunk.value[0].startSide - this.last.endSide) < 0) 3482 return false; 3483 if (this.from.length) 3484 this.finishChunk(true); 3485 this.setMaxPoint = Math.max(this.setMaxPoint, chunk.maxPoint); 3486 this.chunks.push(chunk); 3487 this.chunkPos.push(from); 3488 let last = chunk.value.length - 1; 3489 this.last = chunk.value[last]; 3490 this.lastFrom = chunk.from[last] + from; 3491 this.lastTo = chunk.to[last] + from; 3492 return true; 3493 } 3494 /** 3495 Finish the range set. Returns the new set. The builder can't be 3496 used anymore after this has been called. 3497 */ 3498 finish() { return this.finishInner(RangeSet.empty); } 3499 /** 3500 @internal 3501 */ 3502 finishInner(next) { 3503 if (this.from.length) 3504 this.finishChunk(false); 3505 if (this.chunks.length == 0) 3506 return next; 3507 let result = RangeSet.create(this.chunkPos, this.chunks, this.nextLayer ? this.nextLayer.finishInner(next) : next, this.setMaxPoint); 3508 this.from = null; // Make sure further `add` calls produce errors 3509 return result; 3510 } 3511} 3512function findSharedChunks(a, b, textDiff) { 3513 let inA = new Map(); 3514 for (let set of a) 3515 for (let i = 0; i < set.chunk.length; i++) 3516 if (set.chunk[i].maxPoint <= 0) 3517 inA.set(set.chunk[i], set.chunkPos[i]); 3518 let shared = new Set(); 3519 for (let set of b) 3520 for (let i = 0; i < set.chunk.length; i++) { 3521 let known = inA.get(set.chunk[i]); 3522 if (known != null && (textDiff ? textDiff.mapPos(known) : known) == set.chunkPos[i] && 3523 !(textDiff === null || textDiff === void 0 ? void 0 : textDiff.touchesRange(known, known + set.chunk[i].length))) 3524 shared.add(set.chunk[i]); 3525 } 3526 return shared; 3527} 3528class LayerCursor { 3529 constructor(layer, skip, minPoint, rank = 0) { 3530 this.layer = layer; 3531 this.skip = skip; 3532 this.minPoint = minPoint; 3533 this.rank = rank; 3534 } 3535 get startSide() { return this.value ? this.value.startSide : 0; } 3536 get endSide() { return this.value ? this.value.endSide : 0; } 3537 goto(pos, side = -1000000000 /* C.Far */) { 3538 this.chunkIndex = this.rangeIndex = 0; 3539 this.gotoInner(pos, side, false); 3540 return this; 3541 } 3542 gotoInner(pos, side, forward) { 3543 while (this.chunkIndex < this.layer.chunk.length) { 3544 let next = this.layer.chunk[this.chunkIndex]; 3545 if (!(this.skip && this.skip.has(next) || 3546 this.layer.chunkEnd(this.chunkIndex) < pos || 3547 next.maxPoint < this.minPoint)) 3548 break; 3549 this.chunkIndex++; 3550 forward = false; 3551 } 3552 if (this.chunkIndex < this.layer.chunk.length) { 3553 let rangeIndex = this.layer.chunk[this.chunkIndex].findIndex(pos - this.layer.chunkPos[this.chunkIndex], side, true); 3554 if (!forward || this.rangeIndex < rangeIndex) 3555 this.setRangeIndex(rangeIndex); 3556 } 3557 this.next(); 3558 } 3559 forward(pos, side) { 3560 if ((this.to - pos || this.endSide - side) < 0) 3561 this.gotoInner(pos, side, true); 3562 } 3563 next() { 3564 for (;;) { 3565 if (this.chunkIndex == this.layer.chunk.length) { 3566 this.from = this.to = 1000000000 /* C.Far */; 3567 this.value = null; 3568 break; 3569 } 3570 else { 3571 let chunkPos = this.layer.chunkPos[this.chunkIndex], chunk = this.layer.chunk[this.chunkIndex]; 3572 let from = chunkPos + chunk.from[this.rangeIndex]; 3573 this.from = from; 3574 this.to = chunkPos + chunk.to[this.rangeIndex]; 3575 this.value = chunk.value[this.rangeIndex]; 3576 this.setRangeIndex(this.rangeIndex + 1); 3577 if (this.minPoint < 0 || this.value.point && this.to - this.from >= this.minPoint) 3578 break; 3579 } 3580 } 3581 } 3582 setRangeIndex(index) { 3583 if (index == this.layer.chunk[this.chunkIndex].value.length) { 3584 this.chunkIndex++; 3585 if (this.skip) { 3586 while (this.chunkIndex < this.layer.chunk.length && this.skip.has(this.layer.chunk[this.chunkIndex])) 3587 this.chunkIndex++; 3588 } 3589 this.rangeIndex = 0; 3590 } 3591 else { 3592 this.rangeIndex = index; 3593 } 3594 } 3595 nextChunk() { 3596 this.chunkIndex++; 3597 this.rangeIndex = 0; 3598 this.next(); 3599 } 3600 compare(other) { 3601 return this.from - other.from || this.startSide - other.startSide || this.rank - other.rank || 3602 this.to - other.to || this.endSide - other.endSide; 3603 } 3604} 3605class HeapCursor { 3606 constructor(heap) { 3607 this.heap = heap; 3608 } 3609 static from(sets, skip = null, minPoint = -1) { 3610 let heap = []; 3611 for (let i = 0; i < sets.length; i++) { 3612 for (let cur = sets[i]; !cur.isEmpty; cur = cur.nextLayer) { 3613 if (cur.maxPoint >= minPoint) 3614 heap.push(new LayerCursor(cur, skip, minPoint, i)); 3615 } 3616 } 3617 return heap.length == 1 ? heap[0] : new HeapCursor(heap); 3618 } 3619 get startSide() { return this.value ? this.value.startSide : 0; } 3620 goto(pos, side = -1000000000 /* C.Far */) { 3621 for (let cur of this.heap) 3622 cur.goto(pos, side); 3623 for (let i = this.heap.length >> 1; i >= 0; i--) 3624 heapBubble(this.heap, i); 3625 this.next(); 3626 return this; 3627 } 3628 forward(pos, side) { 3629 for (let cur of this.heap) 3630 cur.forward(pos, side); 3631 for (let i = this.heap.length >> 1; i >= 0; i--) 3632 heapBubble(this.heap, i); 3633 if ((this.to - pos || this.value.endSide - side) < 0) 3634 this.next(); 3635 } 3636 next() { 3637 if (this.heap.length == 0) { 3638 this.from = this.to = 1000000000 /* C.Far */; 3639 this.value = null; 3640 this.rank = -1; 3641 } 3642 else { 3643 let top = this.heap[0]; 3644 this.from = top.from; 3645 this.to = top.to; 3646 this.value = top.value; 3647 this.rank = top.rank; 3648 if (top.value) 3649 top.next(); 3650 heapBubble(this.heap, 0); 3651 } 3652 } 3653} 3654function heapBubble(heap, index) { 3655 for (let cur = heap[index];;) { 3656 let childIndex = (index << 1) + 1; 3657 if (childIndex >= heap.length) 3658 break; 3659 let child = heap[childIndex]; 3660 if (childIndex + 1 < heap.length && child.compare(heap[childIndex + 1]) >= 0) { 3661 child = heap[childIndex + 1]; 3662 childIndex++; 3663 } 3664 if (cur.compare(child) < 0) 3665 break; 3666 heap[childIndex] = cur; 3667 heap[index] = child; 3668 index = childIndex; 3669 } 3670} 3671class SpanCursor { 3672 constructor(sets, skip, minPoint) { 3673 this.minPoint = minPoint; 3674 this.active = []; 3675 this.activeTo = []; 3676 this.activeRank = []; 3677 this.minActive = -1; 3678 // A currently active point range, if any 3679 this.point = null; 3680 this.pointFrom = 0; 3681 this.pointRank = 0; 3682 this.to = -1000000000 /* C.Far */; 3683 this.endSide = 0; 3684 // The amount of open active ranges at the start of the iterator. 3685 // Not including points. 3686 this.openStart = -1; 3687 this.cursor = HeapCursor.from(sets, skip, minPoint); 3688 } 3689 goto(pos, side = -1000000000 /* C.Far */) { 3690 this.cursor.goto(pos, side); 3691 this.active.length = this.activeTo.length = this.activeRank.length = 0; 3692 this.minActive = -1; 3693 this.to = pos; 3694 this.endSide = side; 3695 this.openStart = -1; 3696 this.next(); 3697 return this; 3698 } 3699 forward(pos, side) { 3700 while (this.minActive > -1 && (this.activeTo[this.minActive] - pos || this.active[this.minActive].endSide - side) < 0) 3701 this.removeActive(this.minActive); 3702 this.cursor.forward(pos, side); 3703 } 3704 removeActive(index) { 3705 remove(this.active, index); 3706 remove(this.activeTo, index); 3707 remove(this.activeRank, index); 3708 this.minActive = findMinIndex(this.active, this.activeTo); 3709 } 3710 addActive(trackOpen) { 3711 let i = 0, { value, to, rank } = this.cursor; 3712 // Organize active marks by rank first, then by size 3713 while (i < this.activeRank.length && (rank - this.activeRank[i] || to - this.activeTo[i]) > 0) 3714 i++; 3715 insert(this.active, i, value); 3716 insert(this.activeTo, i, to); 3717 insert(this.activeRank, i, rank); 3718 if (trackOpen) 3719 insert(trackOpen, i, this.cursor.from); 3720 this.minActive = findMinIndex(this.active, this.activeTo); 3721 } 3722 // After calling this, if `this.point` != null, the next range is a 3723 // point. Otherwise, it's a regular range, covered by `this.active`. 3724 next() { 3725 let from = this.to, wasPoint = this.point; 3726 this.point = null; 3727 let trackOpen = this.openStart < 0 ? [] : null; 3728 for (;;) { 3729 let a = this.minActive; 3730 if (a > -1 && (this.activeTo[a] - this.cursor.from || this.active[a].endSide - this.cursor.startSide) < 0) { 3731 if (this.activeTo[a] > from) { 3732 this.to = this.activeTo[a]; 3733 this.endSide = this.active[a].endSide; 3734 break; 3735 } 3736 this.removeActive(a); 3737 if (trackOpen) 3738 remove(trackOpen, a); 3739 } 3740 else if (!this.cursor.value) { 3741 this.to = this.endSide = 1000000000 /* C.Far */; 3742 break; 3743 } 3744 else if (this.cursor.from > from) { 3745 this.to = this.cursor.from; 3746 this.endSide = this.cursor.startSide; 3747 break; 3748 } 3749 else { 3750 let nextVal = this.cursor.value; 3751 if (!nextVal.point) { // Opening a range 3752 this.addActive(trackOpen); 3753 this.cursor.next(); 3754 } 3755 else if (wasPoint && this.cursor.to == this.to && this.cursor.from < this.cursor.to) { 3756 // Ignore any non-empty points that end precisely at the end of the prev point 3757 this.cursor.next(); 3758 } 3759 else { // New point 3760 this.point = nextVal; 3761 this.pointFrom = this.cursor.from; 3762 this.pointRank = this.cursor.rank; 3763 this.to = this.cursor.to; 3764 this.endSide = nextVal.endSide; 3765 this.cursor.next(); 3766 this.forward(this.to, this.endSide); 3767 break; 3768 } 3769 } 3770 } 3771 if (trackOpen) { 3772 this.openStart = 0; 3773 for (let i = trackOpen.length - 1; i >= 0 && trackOpen[i] < from; i--) 3774 this.openStart++; 3775 } 3776 } 3777 activeForPoint(to) { 3778 if (!this.active.length) 3779 return this.active; 3780 let active = []; 3781 for (let i = this.active.length - 1; i >= 0; i--) { 3782 if (this.activeRank[i] < this.pointRank) 3783 break; 3784 if (this.activeTo[i] > to || this.activeTo[i] == to && this.active[i].endSide >= this.point.endSide) 3785 active.push(this.active[i]); 3786 } 3787 return active.reverse(); 3788 } 3789 openEnd(to) { 3790 let open = 0; 3791 for (let i = this.activeTo.length - 1; i >= 0 && this.activeTo[i] > to; i--) 3792 open++; 3793 return open; 3794 } 3795} 3796function compare(a, startA, b, startB, length, comparator) { 3797 a.goto(startA); 3798 b.goto(startB); 3799 let endB = startB + length; 3800 let pos = startB, dPos = startB - startA; 3801 let bounds = !!comparator.boundChange; 3802 for (let boundChange = false;;) { 3803 let dEnd = (a.to + dPos) - b.to, diff = dEnd || a.endSide - b.endSide; 3804 let end = diff < 0 ? a.to + dPos : b.to, clipEnd = Math.min(end, endB); 3805 let point = a.point || b.point; 3806 if (point) { 3807 if (!(a.point && b.point && cmpVal(a.point, b.point) && 3808 sameValues(a.activeForPoint(a.to), b.activeForPoint(b.to)))) 3809 comparator.comparePoint(pos, clipEnd, a.point, b.point); 3810 boundChange = false; 3811 } 3812 else { 3813 if (boundChange) 3814 comparator.boundChange(pos); 3815 if (clipEnd > pos && !sameValues(a.active, b.active)) 3816 comparator.compareRange(pos, clipEnd, a.active, b.active); 3817 if (bounds && clipEnd < endB && (dEnd || a.openEnd(end) != b.openEnd(end))) 3818 boundChange = true; 3819 } 3820 if (end > endB) 3821 break; 3822 pos = end; 3823 if (diff <= 0) 3824 a.next(); 3825 if (diff >= 0) 3826 b.next(); 3827 } 3828} 3829function sameValues(a, b) { 3830 if (a.length != b.length) 3831 return false; 3832 for (let i = 0; i < a.length; i++) 3833 if (a[i] != b[i] && !cmpVal(a[i], b[i])) 3834 return false; 3835 return true; 3836} 3837function remove(array, index) { 3838 for (let i = index, e = array.length - 1; i < e; i++) 3839 array[i] = array[i + 1]; 3840 array.pop(); 3841} 3842function insert(array, index, value) { 3843 for (let i = array.length - 1; i >= index; i--) 3844 array[i + 1] = array[i]; 3845 array[index] = value; 3846} 3847function findMinIndex(value, array) { 3848 let found = -1, foundPos = 1000000000 /* C.Far */; 3849 for (let i = 0; i < array.length; i++) 3850 if ((array[i] - foundPos || value[i].endSide - value[found].endSide) < 0) { 3851 found = i; 3852 foundPos = array[i]; 3853 } 3854 return found; 3855} 3856 3857/** 3858Count the column position at the given offset into the string, 3859taking extending characters and tab size into account. 3860*/ 3861function countColumn(string, tabSize, to = string.length) { 3862 let n = 0; 3863 for (let i = 0; i < to && i < string.length;) { 3864 if (string.charCodeAt(i) == 9) { 3865 n += tabSize - (n % tabSize); 3866 i++; 3867 } 3868 else { 3869 n++; 3870 i = findClusterBreak(string, i); 3871 } 3872 } 3873 return n; 3874} 3875/** 3876Find the offset that corresponds to the given column position in a 3877string, taking extending characters and tab size into account. By 3878default, the string length is returned when it is too short to 3879reach the column. Pass `strict` true to make it return -1 in that 3880situation. 3881*/ 3882function findColumn(string, col, tabSize, strict) { 3883 for (let i = 0, n = 0;;) { 3884 if (n >= col) 3885 return i; 3886 if (i == string.length) 3887 break; 3888 n += string.charCodeAt(i) == 9 ? tabSize - (n % tabSize) : 1; 3889 i = findClusterBreak(string, i); 3890 } 3891 return strict === true ? -1 : string.length; 3892} 3893 3894exports.Annotation = Annotation; 3895exports.AnnotationType = AnnotationType; 3896exports.ChangeDesc = ChangeDesc; 3897exports.ChangeSet = ChangeSet; 3898exports.Compartment = Compartment; 3899exports.EditorSelection = EditorSelection; 3900exports.EditorState = EditorState; 3901exports.Facet = Facet; 3902exports.Line = Line; 3903exports.Prec = Prec; 3904exports.Range = Range; 3905exports.RangeSet = RangeSet; 3906exports.RangeSetBuilder = RangeSetBuilder; 3907exports.RangeValue = RangeValue; 3908exports.SelectionRange = SelectionRange; 3909exports.StateEffect = StateEffect; 3910exports.StateEffectType = StateEffectType; 3911exports.StateField = StateField; 3912exports.Text = Text; 3913exports.Transaction = Transaction; 3914exports.codePointAt = codePointAt; 3915exports.codePointSize = codePointSize; 3916exports.combineConfig = combineConfig; 3917exports.countColumn = countColumn; 3918exports.findClusterBreak = findClusterBreak; 3919exports.findColumn = findColumn; 3920exports.fromCodePoint = fromCodePoint;