diff --git a/typecho/write/js/joe.write.chunk.js b/typecho/write/js/joe.write.chunk.js index c298f88..dce36b8 100644 --- a/typecho/write/js/joe.write.chunk.js +++ b/typecho/write/js/joe.write.chunk.js @@ -1,13777 +1,4 @@ -(function () { - 'use strict'; - - // Compressed representation of the Grapheme_Cluster_Break=Extend - // information from - // http://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakProperty.txt. - // Each pair of elements represents a range, as an offet from the - // previous range and a length. Numbers are in base-36, with the empty - // string being a shorthand for 1. - let extend = "lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o".split(",").map(s => s ? parseInt(s, 36) : 1); - // Convert offsets into absolute values - for (let i = 1; i < extend.length; i++) - extend[i] += extend[i - 1]; - function isExtendingChar(code) { - for (let i = 1; i < extend.length; i += 2) - if (extend[i] > code) - return extend[i - 1] <= code; - return false; - } - function isRegionalIndicator(code) { - return code >= 0x1F1E6 && code <= 0x1F1FF; - } - const ZWJ = 0x200d; - /// Returns a next grapheme cluster break _after_ (not equal to) - /// `pos`, if `forward` is true, or before otherwise. Returns `pos` - /// itself if no further cluster break is available in the string. - /// Moves across surrogate pairs, extending characters, characters - /// joined with zero-width joiners, and flag emoji. - function findClusterBreak(str, pos, forward = true) { - return (forward ? nextClusterBreak : prevClusterBreak)(str, pos); - } - function nextClusterBreak(str, pos) { - if (pos == str.length) - return pos; - // If pos is in the middle of a surrogate pair, move to its start - if (pos && surrogateLow(str.charCodeAt(pos)) && surrogateHigh(str.charCodeAt(pos - 1))) - pos--; - let prev = codePointAt(str, pos); - pos += codePointSize(prev); - while (pos < str.length) { - let next = codePointAt(str, pos); - if (prev == ZWJ || next == ZWJ || isExtendingChar(next)) { - pos += codePointSize(next); - prev = next; - } - else if (isRegionalIndicator(next)) { - let countBefore = 0, i = pos - 2; - while (i >= 0 && isRegionalIndicator(codePointAt(str, i))) { - countBefore++; - i -= 2; - } - if (countBefore % 2 == 0) - break; - else - pos += 2; - } - else { - break; - } - } - return pos; - } - function prevClusterBreak(str, pos) { - while (pos > 0) { - let found = nextClusterBreak(str, pos - 2); - if (found < pos) - return found; - pos--; - } - return 0; - } - function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; } - function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; } - /// Find the code point at the given position in a string (like the - /// [`codePointAt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/codePointAt) - /// string method). - function codePointAt(str, pos) { - let code0 = str.charCodeAt(pos); - if (!surrogateHigh(code0) || pos + 1 == str.length) - return code0; - let code1 = str.charCodeAt(pos + 1); - if (!surrogateLow(code1)) - return code0; - return ((code0 - 0xd800) << 10) + (code1 - 0xdc00) + 0x10000; - } - /// Given a Unicode codepoint, return the JavaScript string that - /// respresents it (like - /// [`String.fromCodePoint`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint)). - function fromCodePoint(code) { - if (code <= 0xffff) - return String.fromCharCode(code); - code -= 0x10000; - return String.fromCharCode((code >> 10) + 0xd800, (code & 1023) + 0xdc00); - } - /// The first character that takes up two positions in a JavaScript - /// string. It is often useful to compare with this after calling - /// `codePointAt`, to figure out whether your character takes up 1 or - /// 2 index positions. - function codePointSize(code) { return code < 0x10000 ? 1 : 2; } - - /// Count the column position at the given offset into the string, - /// taking extending characters and tab size into account. - function countColumn(string, n, tabSize) { - for (let i = 0; i < string.length;) { - if (string.charCodeAt(i) == 9) { - n += tabSize - (n % tabSize); - i++; - } - else { - n++; - i = findClusterBreak(string, i); - } - } - return n; - } - /// Find the offset that corresponds to the given column position in a - /// string, taking extending characters and tab size into account. - function findColumn(string, n, col, tabSize) { - for (let i = 0; i < string.length;) { - if (n >= col) - return { offset: i, leftOver: 0 }; - n += string.charCodeAt(i) == 9 ? tabSize - (n % tabSize) : 1; - i = findClusterBreak(string, i); - } - return { offset: string.length, leftOver: col - n }; - } - - /// The data structure for documents. - class Text { - /// @internal - constructor() { } - /// Get the line description around the given position. - lineAt(pos) { - if (pos < 0 || pos > this.length) - throw new RangeError(`Invalid position ${pos} in document of length ${this.length}`); - return this.lineInner(pos, false, 1, 0); - } - /// Get the description for the given (1-based) line number. - line(n) { - if (n < 1 || n > this.lines) - throw new RangeError(`Invalid line number ${n} in ${this.lines}-line document`); - return this.lineInner(n, true, 1, 0); - } - /// Replace a range of the text with the given content. - replace(from, to, text) { - let parts = []; - this.decompose(0, from, parts, 2 /* To */); - if (text.length) - text.decompose(0, text.length, parts, 1 /* From */ | 2 /* To */); - this.decompose(to, this.length, parts, 1 /* From */); - return TextNode.from(parts, this.length - (to - from) + text.length); - } - /// Append another document to this one. - append(other) { - return this.replace(this.length, this.length, other); - } - /// Retrieve the text between the given points. - slice(from, to = this.length) { - let parts = []; - this.decompose(from, to, parts, 0); - return TextNode.from(parts, to - from); - } - /// Test whether this text is equal to another instance. - eq(other) { - if (other == this) - return true; - if (other.length != this.length || other.lines != this.lines) - return false; - let a = new RawTextCursor(this), b = new RawTextCursor(other); - for (;;) { - a.next(); - b.next(); - if (a.lineBreak != b.lineBreak || a.done != b.done || a.value != b.value) - return false; - if (a.done) - return true; - } - } - /// Iterate over the text. When `dir` is `-1`, iteration happens - /// from end to start. This will return lines and the breaks between - /// them as separate strings, and for long lines, might split lines - /// themselves into multiple chunks as well. - iter(dir = 1) { return new RawTextCursor(this, dir); } - /// Iterate over a range of the text. When `from` > `to`, the - /// iterator will run in reverse. - iterRange(from, to = this.length) { return new PartialTextCursor(this, from, to); } - /// @internal - toString() { return this.sliceString(0); } - /// Convert the document to an array of lines (which can be - /// deserialized again via [`Text.of`](#text.Text^of)). - toJSON() { - let lines = []; - this.flatten(lines); - return lines; - } - /// Create a `Text` instance for the given array of lines. - static of(text) { - if (text.length == 0) - throw new RangeError("A document must have at least one line"); - if (text.length == 1 && !text[0]) - return Text.empty; - return text.length <= 32 /* Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, [])); - } - } - if (typeof Symbol != "undefined") - Text.prototype[Symbol.iterator] = function () { return this.iter(); }; - // Leaves store an array of line strings. There are always line breaks - // between these strings. Leaves are limited in size and have to be - // contained in TextNode instances for bigger documents. - class TextLeaf extends Text { - constructor(text, length = textLength(text)) { - super(); - this.text = text; - this.length = length; - } - get lines() { return this.text.length; } - get children() { return null; } - lineInner(target, isLine, line, offset) { - for (let i = 0;; i++) { - let string = this.text[i], end = offset + string.length; - if ((isLine ? line : end) >= target) - return new Line(offset, end, line, string); - offset = end + 1; - line++; - } - } - decompose(from, to, target, open) { - let text = from <= 0 && to >= this.length ? this - : new TextLeaf(sliceText(this.text, from, to), Math.min(to, this.length) - Math.max(0, from)); - if (open & 1 /* From */) { - let prev = target.pop(); - let joined = appendText(text.text, prev.text.slice(), 0, text.length); - if (joined.length <= 32 /* Branch */) { - target.push(new TextLeaf(joined, prev.length + text.length)); - } - else { - let mid = joined.length >> 1; - target.push(new TextLeaf(joined.slice(0, mid)), new TextLeaf(joined.slice(mid))); - } - } - else { - target.push(text); - } - } - replace(from, to, text) { - if (!(text instanceof TextLeaf)) - return super.replace(from, to, text); - let lines = appendText(this.text, appendText(text.text, sliceText(this.text, 0, from)), to); - let newLen = this.length + text.length - (to - from); - if (lines.length <= 32 /* Branch */) - return new TextLeaf(lines, newLen); - return TextNode.from(TextLeaf.split(lines, []), newLen); - } - sliceString(from, to = this.length, lineSep = "\n") { - let result = ""; - for (let pos = 0, i = 0; pos <= to && i < this.text.length; i++) { - let line = this.text[i], end = pos + line.length; - if (pos > from && i) - result += lineSep; - if (from < end && to > pos) - result += line.slice(Math.max(0, from - pos), to - pos); - pos = end + 1; - } - return result; - } - flatten(target) { - for (let line of this.text) - target.push(line); - } - static split(text, target) { - let part = [], len = -1; - for (let line of text) { - part.push(line); - len += line.length + 1; - if (part.length == 32 /* Branch */) { - target.push(new TextLeaf(part, len)); - part = []; - len = -1; - } - } - if (len > -1) - target.push(new TextLeaf(part, len)); - return target; - } - } - // Nodes provide the tree structure of the `Text` type. They store a - // number of other nodes or leaves, taking care to balance themselves - // on changes. There are implied line breaks _between_ the children of - // a node (but not before the first or after the last child). - class TextNode extends Text { - constructor(children, length) { - super(); - this.children = children; - this.length = length; - this.lines = 0; - for (let child of children) - this.lines += child.lines; - } - lineInner(target, isLine, line, offset) { - for (let i = 0;; i++) { - let child = this.children[i], end = offset + child.length, endLine = line + child.lines - 1; - if ((isLine ? endLine : end) >= target) - return child.lineInner(target, isLine, line, offset); - offset = end + 1; - line = endLine + 1; - } - } - decompose(from, to, target, open) { - for (let i = 0, pos = 0; pos <= to && i < this.children.length; i++) { - let child = this.children[i], end = pos + child.length; - if (from <= end && to >= pos) { - let childOpen = open & ((pos <= from ? 1 /* From */ : 0) | (end >= to ? 2 /* To */ : 0)); - if (pos >= from && end <= to && !childOpen) - target.push(child); - else - child.decompose(from - pos, to - pos, target, childOpen); - } - pos = end + 1; - } - } - replace(from, to, text) { - if (text.lines < this.lines) - for (let i = 0, pos = 0; i < this.children.length; i++) { - let child = this.children[i], end = pos + child.length; - // Fast path: if the change only affects one child and the - // child's size remains in the acceptable range, only update - // that child - if (from >= pos && to <= end) { - let updated = child.replace(from - pos, to - pos, text); - let totalLines = this.lines - child.lines + updated.lines; - if (updated.lines < (totalLines >> (5 /* BranchShift */ - 1)) && - updated.lines > (totalLines >> (5 /* BranchShift */ + 1))) { - let copy = this.children.slice(); - copy[i] = updated; - return new TextNode(copy, this.length - (to - from) + text.length); - } - return super.replace(pos, end, updated); - } - pos = end + 1; - } - return super.replace(from, to, text); - } - sliceString(from, to = this.length, lineSep = "\n") { - let result = ""; - for (let i = 0, pos = 0; i < this.children.length && pos <= to; i++) { - let child = this.children[i], end = pos + child.length; - if (pos > from && i) - result += lineSep; - if (from < end && to > pos) - result += child.sliceString(from - pos, to - pos, lineSep); - pos = end + 1; - } - return result; - } - flatten(target) { - for (let child of this.children) - child.flatten(target); - } - static from(children, length = children.reduce((l, ch) => l + ch.length + 1, -1)) { - let lines = 0; - for (let ch of children) - lines += ch.lines; - if (lines < 32 /* Branch */) { - let flat = []; - for (let ch of children) - ch.flatten(flat); - return new TextLeaf(flat, length); - } - let chunk = Math.max(32 /* Branch */, lines >> 5 /* BranchShift */), maxChunk = chunk << 1, minChunk = chunk >> 1; - let chunked = [], currentLines = 0, currentLen = -1, currentChunk = []; - function add(child) { - let last; - if (child.lines > maxChunk && child instanceof TextNode) { - for (let node of child.children) - add(node); - } - else if (child.lines > minChunk && (currentLines > minChunk || !currentLines)) { - flush(); - chunked.push(child); - } - else if (child instanceof TextLeaf && currentLines && - (last = currentChunk[currentChunk.length - 1]) instanceof TextLeaf && - child.lines + last.lines <= 32 /* Branch */) { - currentLines += child.lines; - currentLen += child.length + 1; - currentChunk[currentChunk.length - 1] = new TextLeaf(last.text.concat(child.text), last.length + 1 + child.length); - } - else { - if (currentLines + child.lines > chunk) - flush(); - currentLines += child.lines; - currentLen += child.length + 1; - currentChunk.push(child); - } - } - function flush() { - if (currentLines == 0) - return; - chunked.push(currentChunk.length == 1 ? currentChunk[0] : TextNode.from(currentChunk, currentLen)); - currentLen = -1; - currentLines = currentChunk.length = 0; - } - for (let child of children) - add(child); - flush(); - return chunked.length == 1 ? chunked[0] : new TextNode(chunked, length); - } - } - Text.empty = new TextLeaf([""], 0); - function textLength(text) { - let length = -1; - for (let line of text) - length += line.length + 1; - return length; - } - function appendText(text, target, from = 0, to = 1e9) { - for (let pos = 0, i = 0, first = true; i < text.length && pos <= to; i++) { - let line = text[i], end = pos + line.length; - if (end >= from) { - if (end > to) - line = line.slice(0, to - pos); - if (pos < from) - line = line.slice(from - pos); - if (first) { - target[target.length - 1] += line; - first = false; - } - else - target.push(line); - } - pos = end + 1; - } - return target; - } - function sliceText(text, from, to) { - return appendText(text, [""], from, to); - } - class RawTextCursor { - constructor(text, dir = 1) { - this.dir = dir; - this.done = false; - this.lineBreak = false; - this.value = ""; - this.nodes = [text]; - this.offsets = [dir > 0 ? 0 : text instanceof TextLeaf ? text.text.length : text.children.length]; - } - next(skip = 0) { - for (;;) { - let last = this.nodes.length - 1; - if (last < 0) { - this.done = true; - this.value = ""; - this.lineBreak = false; - return this; - } - let top = this.nodes[last], offset = this.offsets[last]; - let size = top instanceof TextLeaf ? top.text.length : top.children.length; - if (offset == (this.dir > 0 ? size : 0)) { - this.nodes.pop(); - this.offsets.pop(); - } - else if (!this.lineBreak && offset != (this.dir > 0 ? 0 : size)) { - // Internal offset with lineBreak == false means we have to - // count the line break at this position - this.lineBreak = true; - if (skip == 0) { - this.value = "\n"; - return this; - } - skip--; - } - else if (top instanceof TextLeaf) { - // Move to the next string - let next = top.text[offset - (this.dir < 0 ? 1 : 0)]; - this.offsets[last] = (offset += this.dir); - this.lineBreak = false; - if (next.length > Math.max(0, skip)) { - this.value = skip == 0 ? next : this.dir > 0 ? next.slice(skip) : next.slice(0, next.length - skip); - return this; - } - skip -= next.length; - } - else { - let next = top.children[this.dir > 0 ? offset : offset - 1]; - this.offsets[last] = offset + this.dir; - this.lineBreak = false; - if (skip > next.length) { - skip -= next.length; - } - else { - this.nodes.push(next); - this.offsets.push(this.dir > 0 ? 0 : next instanceof TextLeaf ? next.text.length : next.children.length); - } - } - } - } - } - class PartialTextCursor { - constructor(text, start, end) { - this.value = ""; - this.cursor = new RawTextCursor(text, start > end ? -1 : 1); - if (start > end) { - this.skip = text.length - start; - this.limit = start - end; - } - else { - this.skip = start; - this.limit = end - start; - } - } - next(skip = 0) { - if (this.limit <= 0) { - this.limit = -1; - } - else { - let { value, lineBreak, done } = this.cursor.next(this.skip + skip); - this.skip = 0; - this.value = value; - let len = lineBreak ? 1 : value.length; - if (len > this.limit) - this.value = this.cursor.dir > 0 ? value.slice(0, this.limit) : value.slice(len - this.limit); - if (done || this.value.length == 0) - this.limit = -1; - else - this.limit -= this.value.length; - } - return this; - } - get lineBreak() { return this.cursor.lineBreak; } - get done() { return this.limit < 0; } - } - /// This type describes a line in the document. It is created - /// on-demand when lines are [queried](#text.Text.lineAt). - class Line { - /// @internal - constructor( - /// The position of the start of the line. - from, - /// The position at the end of the line (_before_ the line break, - /// or at the end of document for the last line). - to, - /// This line's line number (1-based). - number, - /// The line's content. - text) { - this.from = from; - this.to = to; - this.number = number; - this.text = text; - } - /// The length of the line (not including any line break after it). - get length() { return this.to - this.from; } - } - - const DefaultSplit = /\r\n?|\n/; - /** - Distinguishes different ways in which positions can be mapped. - */ - var MapMode; - (function (MapMode) { - /** - Map a position to a valid new position, even when its context - was deleted. - */ - MapMode[MapMode["Simple"] = 0] = "Simple"; - /** - Return null if deletion happens across the position. - */ - MapMode[MapMode["TrackDel"] = 1] = "TrackDel"; - /** - Return null if the character _before_ the position is deleted. - */ - MapMode[MapMode["TrackBefore"] = 2] = "TrackBefore"; - /** - Return null if the character _after_ the position is deleted. - */ - MapMode[MapMode["TrackAfter"] = 3] = "TrackAfter"; - })(MapMode || (MapMode = {})); - /** - A change description is a variant of [change set](https://codemirror.net/6/docs/ref/#state.ChangeSet) - that doesn't store the inserted text. As such, it can't be - applied, but is cheaper to store and manipulate. - */ - class ChangeDesc { - // Sections are encoded as pairs of integers. The first is the - // length in the current document, and the second is -1 for - // unaffected sections, and the length of the replacement content - // otherwise. So an insertion would be (0, n>0), a deletion (n>0, - // 0), and a replacement two positive numbers. - /** - @internal - */ - constructor( - /** - @internal - */ - sections) { - this.sections = sections; - } - /** - The length of the document before the change. - */ - get length() { - let result = 0; - for (let i = 0; i < this.sections.length; i += 2) - result += this.sections[i]; - return result; - } - /** - The length of the document after the change. - */ - get newLength() { - let result = 0; - for (let i = 0; i < this.sections.length; i += 2) { - let ins = this.sections[i + 1]; - result += ins < 0 ? this.sections[i] : ins; - } - return result; - } - /** - False when there are actual changes in this set. - */ - get empty() { return this.sections.length == 0 || this.sections.length == 2 && this.sections[1] < 0; } - /** - Iterate over the unchanged parts left by these changes. - */ - iterGaps(f) { - for (let i = 0, posA = 0, posB = 0; i < this.sections.length;) { - let len = this.sections[i++], ins = this.sections[i++]; - if (ins < 0) { - f(posA, posB, len); - posB += len; - } - else { - posB += ins; - } - posA += len; - } - } - /** - Iterate over the ranges changed by these changes. (See - [`ChangeSet.iterChanges`](https://codemirror.net/6/docs/ref/#state.ChangeSet.iterChanges) for a - variant that also provides you with the inserted text.) - - When `individual` is true, adjacent changes (which are kept - separate for [position mapping](https://codemirror.net/6/docs/ref/#state.ChangeDesc.mapPos)) are - reported separately. - */ - iterChangedRanges(f, individual = false) { - iterChanges(this, f, individual); - } - /** - Get a description of the inverted form of these changes. - */ - get invertedDesc() { - let sections = []; - for (let i = 0; i < this.sections.length;) { - let len = this.sections[i++], ins = this.sections[i++]; - if (ins < 0) - sections.push(len, ins); - else - sections.push(ins, len); - } - return new ChangeDesc(sections); - } - /** - Compute the combined effect of applying another set of changes - after this one. The length of the document after this set should - match the length before `other`. - */ - composeDesc(other) { return this.empty ? other : other.empty ? this : composeSets(this, other); } - /** - Map this description, which should start with the same document - as `other`, over another set of changes, so that it can be - applied after it. When `before` is true, map as if the changes - in `other` happened before the ones in `this`. - */ - mapDesc(other, before = false) { return other.empty ? this : mapSet(this, other, before); } - mapPos(pos, assoc = -1, mode = MapMode.Simple) { - let posA = 0, posB = 0; - for (let i = 0; i < this.sections.length;) { - let len = this.sections[i++], ins = this.sections[i++], endA = posA + len; - if (ins < 0) { - if (endA > pos) - return posB + (pos - posA); - posB += len; - } - else { - if (mode != MapMode.Simple && endA >= pos && - (mode == MapMode.TrackDel && posA < pos && endA > pos || - mode == MapMode.TrackBefore && posA < pos || - mode == MapMode.TrackAfter && endA > pos)) - return null; - if (endA > pos || endA == pos && assoc < 0 && !len) - return pos == posA || assoc < 0 ? posB : posB + ins; - posB += ins; - } - posA = endA; - } - if (pos > posA) - throw new RangeError(`Position ${pos} is out of range for changeset of length ${posA}`); - return posB; - } - /** - Check whether these changes touch a given range. When one of the - changes entirely covers the range, the string `"cover"` is - returned. - */ - touchesRange(from, to = from) { - for (let i = 0, pos = 0; i < this.sections.length && pos <= to;) { - let len = this.sections[i++], ins = this.sections[i++], end = pos + len; - if (ins >= 0 && pos <= to && end >= from) - return pos < from && end > to ? "cover" : true; - pos = end; - } - return false; - } - /** - @internal - */ - toString() { - let result = ""; - for (let i = 0; i < this.sections.length;) { - let len = this.sections[i++], ins = this.sections[i++]; - result += (result ? " " : "") + len + (ins >= 0 ? ":" + ins : ""); - } - return result; - } - /** - Serialize this change desc to a JSON-representable value. - */ - toJSON() { return this.sections; } - /** - Create a change desc from its JSON representation (as produced - by [`toJSON`](https://codemirror.net/6/docs/ref/#state.ChangeDesc.toJSON). - */ - static fromJSON(json) { - if (!Array.isArray(json) || json.length % 2 || json.some(a => typeof a != "number")) - throw new RangeError("Invalid JSON representation of ChangeDesc"); - return new ChangeDesc(json); - } - } - /** - A change set represents a group of modifications to a document. It - stores the document length, and can only be applied to documents - with exactly that length. - */ - class ChangeSet extends ChangeDesc { - /** - @internal - */ - constructor(sections, - /** - @internal - */ - inserted) { - super(sections); - this.inserted = inserted; - } - /** - Apply the changes to a document, returning the modified - document. - */ - apply(doc) { - if (this.length != doc.length) - throw new RangeError("Applying change set to a document with the wrong length"); - iterChanges(this, (fromA, toA, fromB, _toB, text) => doc = doc.replace(fromB, fromB + (toA - fromA), text), false); - return doc; - } - mapDesc(other, before = false) { return mapSet(this, other, before, true); } - /** - Given the document as it existed _before_ the changes, return a - change set that represents the inverse of this set, which could - be used to go from the document created by the changes back to - the document as it existed before the changes. - */ - invert(doc) { - let sections = this.sections.slice(), inserted = []; - for (let i = 0, pos = 0; i < sections.length; i += 2) { - let len = sections[i], ins = sections[i + 1]; - if (ins >= 0) { - sections[i] = ins; - sections[i + 1] = len; - let index = i >> 1; - while (inserted.length < index) - inserted.push(Text.empty); - inserted.push(len ? doc.slice(pos, pos + len) : Text.empty); - } - pos += len; - } - return new ChangeSet(sections, inserted); - } - /** - Combine two subsequent change sets into a single set. `other` - must start in the document produced by `this`. If `this` goes - `docA` → `docB` and `other` represents `docB` → `docC`, the - returned value will represent the change `docA` → `docC`. - */ - compose(other) { return this.empty ? other : other.empty ? this : composeSets(this, other, true); } - /** - Given another change set starting in the same document, maps this - change set over the other, producing a new change set that can be - applied to the document produced by applying `other`. When - `before` is `true`, order changes as if `this` comes before - `other`, otherwise (the default) treat `other` as coming first. - - Given two changes `A` and `B`, `A.compose(B.map(A))` and - `B.compose(A.map(B, true))` will produce the same document. This - provides a basic form of [operational - transformation](https://en.wikipedia.org/wiki/Operational_transformation), - and can be used for collaborative editing. - */ - map(other, before = false) { return other.empty ? this : mapSet(this, other, before, true); } - /** - Iterate over the changed ranges in the document, calling `f` for - each. - - When `individual` is true, adjacent changes are reported - separately. - */ - iterChanges(f, individual = false) { - iterChanges(this, f, individual); - } - /** - Get a [change description](https://codemirror.net/6/docs/ref/#state.ChangeDesc) for this change - set. - */ - get desc() { return new ChangeDesc(this.sections); } - /** - @internal - */ - filter(ranges) { - let resultSections = [], resultInserted = [], filteredSections = []; - let iter = new SectionIter(this); - done: for (let i = 0, pos = 0;;) { - let next = i == ranges.length ? 1e9 : ranges[i++]; - while (pos < next || pos == next && iter.len == 0) { - if (iter.done) - break done; - let len = Math.min(iter.len, next - pos); - addSection(filteredSections, len, -1); - let ins = iter.ins == -1 ? -1 : iter.off == 0 ? iter.ins : 0; - addSection(resultSections, len, ins); - if (ins > 0) - addInsert(resultInserted, resultSections, iter.text); - iter.forward(len); - pos += len; - } - let end = ranges[i++]; - while (pos < end) { - if (iter.done) - break done; - let len = Math.min(iter.len, end - pos); - addSection(resultSections, len, -1); - addSection(filteredSections, len, iter.ins == -1 ? -1 : iter.off == 0 ? iter.ins : 0); - iter.forward(len); - pos += len; - } - } - return { changes: new ChangeSet(resultSections, resultInserted), - filtered: new ChangeDesc(filteredSections) }; - } - /** - Serialize this change set to a JSON-representable value. - */ - toJSON() { - let parts = []; - for (let i = 0; i < this.sections.length; i += 2) { - let len = this.sections[i], ins = this.sections[i + 1]; - if (ins < 0) - parts.push(len); - else if (ins == 0) - parts.push([len]); - else - parts.push([len].concat(this.inserted[i >> 1].toJSON())); - } - return parts; - } - /** - Create a change set for the given changes, for a document of the - given length, using `lineSep` as line separator. - */ - static of(changes, length, lineSep) { - let sections = [], inserted = [], pos = 0; - let total = null; - function flush(force = false) { - if (!force && !sections.length) - return; - if (pos < length) - addSection(sections, length - pos, -1); - let set = new ChangeSet(sections, inserted); - total = total ? total.compose(set.map(total)) : set; - sections = []; - inserted = []; - pos = 0; - } - function process(spec) { - if (Array.isArray(spec)) { - for (let sub of spec) - process(sub); - } - else if (spec instanceof ChangeSet) { - if (spec.length != length) - throw new RangeError(`Mismatched change set length (got ${spec.length}, expected ${length})`); - flush(); - total = total ? total.compose(spec.map(total)) : spec; - } - else { - let { from, to = from, insert } = spec; - if (from > to || from < 0 || to > length) - throw new RangeError(`Invalid change range ${from} to ${to} (in doc of length ${length})`); - let insText = !insert ? Text.empty : typeof insert == "string" ? Text.of(insert.split(lineSep || DefaultSplit)) : insert; - let insLen = insText.length; - if (from == to && insLen == 0) - return; - if (from < pos) - flush(); - if (from > pos) - addSection(sections, from - pos, -1); - addSection(sections, to - from, insLen); - addInsert(inserted, sections, insText); - pos = to; - } - } - process(changes); - flush(!total); - return total; - } - /** - Create an empty changeset of the given length. - */ - static empty(length) { - return new ChangeSet(length ? [length, -1] : [], []); - } - /** - Create a changeset from its JSON representation (as produced by - [`toJSON`](https://codemirror.net/6/docs/ref/#state.ChangeSet.toJSON). - */ - static fromJSON(json) { - if (!Array.isArray(json)) - throw new RangeError("Invalid JSON representation of ChangeSet"); - let sections = [], inserted = []; - for (let i = 0; i < json.length; i++) { - let part = json[i]; - if (typeof part == "number") { - sections.push(part, -1); - } - else if (!Array.isArray(part) || typeof part[0] != "number" || part.some((e, i) => i && typeof e != "string")) { - throw new RangeError("Invalid JSON representation of ChangeSet"); - } - else if (part.length == 1) { - sections.push(part[0], 0); - } - else { - while (inserted.length < i) - inserted.push(Text.empty); - inserted[i] = Text.of(part.slice(1)); - sections.push(part[0], inserted[i].length); - } - } - return new ChangeSet(sections, inserted); - } - } - function addSection(sections, len, ins, forceJoin = false) { - if (len == 0 && ins <= 0) - return; - let last = sections.length - 2; - if (last >= 0 && ins <= 0 && ins == sections[last + 1]) - sections[last] += len; - else if (len == 0 && sections[last] == 0) - sections[last + 1] += ins; - else if (forceJoin) { - sections[last] += len; - sections[last + 1] += ins; - } - else - sections.push(len, ins); - } - function addInsert(values, sections, value) { - if (value.length == 0) - return; - let index = (sections.length - 2) >> 1; - if (index < values.length) { - values[values.length - 1] = values[values.length - 1].append(value); - } - else { - while (values.length < index) - values.push(Text.empty); - values.push(value); - } - } - function iterChanges(desc, f, individual) { - let inserted = desc.inserted; - for (let posA = 0, posB = 0, i = 0; i < desc.sections.length;) { - let len = desc.sections[i++], ins = desc.sections[i++]; - if (ins < 0) { - posA += len; - posB += len; - } - else { - let endA = posA, endB = posB, text = Text.empty; - for (;;) { - endA += len; - endB += ins; - if (ins && inserted) - text = text.append(inserted[(i - 2) >> 1]); - if (individual || i == desc.sections.length || desc.sections[i + 1] < 0) - break; - len = desc.sections[i++]; - ins = desc.sections[i++]; - } - f(posA, endA, posB, endB, text); - posA = endA; - posB = endB; - } - } - } - function mapSet(setA, setB, before, mkSet = false) { - let sections = [], insert = mkSet ? [] : null; - let a = new SectionIter(setA), b = new SectionIter(setB); - for (let posA = 0, posB = 0;;) { - if (a.ins == -1) { - posA += a.len; - a.next(); - } - else if (b.ins == -1 && posB < posA) { - let skip = Math.min(b.len, posA - posB); - b.forward(skip); - addSection(sections, skip, -1); - posB += skip; - } - else if (b.ins >= 0 && (a.done || posB < posA || posB == posA && (b.len < a.len || b.len == a.len && !before))) { - addSection(sections, b.ins, -1); - while (posA > posB && !a.done && posA + a.len < posB + b.len) { - posA += a.len; - a.next(); - } - posB += b.len; - b.next(); - } - else if (a.ins >= 0) { - let len = 0, end = posA + a.len; - for (;;) { - if (b.ins >= 0 && posB > posA && posB + b.len < end) { - len += b.ins; - posB += b.len; - b.next(); - } - else if (b.ins == -1 && posB < end) { - let skip = Math.min(b.len, end - posB); - len += skip; - b.forward(skip); - posB += skip; - } - else { - break; - } - } - addSection(sections, len, a.ins); - if (insert) - addInsert(insert, sections, a.text); - posA = end; - a.next(); - } - else if (a.done && b.done) { - return insert ? new ChangeSet(sections, insert) : new ChangeDesc(sections); - } - else { - throw new Error("Mismatched change set lengths"); - } - } - } - function composeSets(setA, setB, mkSet = false) { - let sections = []; - let insert = mkSet ? [] : null; - let a = new SectionIter(setA), b = new SectionIter(setB); - for (let open = false;;) { - if (a.done && b.done) { - return insert ? new ChangeSet(sections, insert) : new ChangeDesc(sections); - } - else if (a.ins == 0) { // Deletion in A - addSection(sections, a.len, 0, open); - a.next(); - } - else if (b.len == 0 && !b.done) { // Insertion in B - addSection(sections, 0, b.ins, open); - if (insert) - addInsert(insert, sections, b.text); - b.next(); - } - else if (a.done || b.done) { - throw new Error("Mismatched change set lengths"); - } - else { - let len = Math.min(a.len2, b.len), sectionLen = sections.length; - if (a.ins == -1) { - let insB = b.ins == -1 ? -1 : b.off ? 0 : b.ins; - addSection(sections, len, insB, open); - if (insert && insB) - addInsert(insert, sections, b.text); - } - else if (b.ins == -1) { - addSection(sections, a.off ? 0 : a.len, len, open); - if (insert) - addInsert(insert, sections, a.textBit(len)); - } - else { - addSection(sections, a.off ? 0 : a.len, b.off ? 0 : b.ins, open); - if (insert && !b.off) - addInsert(insert, sections, b.text); - } - open = (a.ins > len || b.ins >= 0 && b.len > len) && (open || sections.length > sectionLen); - a.forward2(len); - b.forward(len); - } - } - } - class SectionIter { - constructor(set) { - this.set = set; - this.i = 0; - this.next(); - } - next() { - let { sections } = this.set; - if (this.i < sections.length) { - this.len = sections[this.i++]; - this.ins = sections[this.i++]; - } - else { - this.len = 0; - this.ins = -2; - } - this.off = 0; - } - get done() { return this.ins == -2; } - get len2() { return this.ins < 0 ? this.len : this.ins; } - get text() { - let { inserted } = this.set, index = (this.i - 2) >> 1; - return index >= inserted.length ? Text.empty : inserted[index]; - } - textBit(len) { - let { inserted } = this.set, index = (this.i - 2) >> 1; - return index >= inserted.length && !len ? Text.empty - : inserted[index].slice(this.off, len == null ? undefined : this.off + len); - } - forward(len) { - if (len == this.len) - this.next(); - else { - this.len -= len; - this.off += len; - } - } - forward2(len) { - if (this.ins == -1) - this.forward(len); - else if (len == this.ins) - this.next(); - else { - this.ins -= len; - this.off += len; - } - } - } - - /** - A single selection range. When - [`allowMultipleSelections`](https://codemirror.net/6/docs/ref/#state.EditorState^allowMultipleSelections) - is enabled, a [selection](https://codemirror.net/6/docs/ref/#state.EditorSelection) may hold - multiple ranges. By default, selections hold exactly one range. - */ - class SelectionRange { - /** - @internal - */ - constructor( - /** - The lower boundary of the range. - */ - from, - /** - The upper boundary of the range. - */ - to, flags) { - this.from = from; - this.to = to; - this.flags = flags; - } - /** - The anchor of the range—the side that doesn't move when you - extend it. - */ - get anchor() { return this.flags & 16 /* Inverted */ ? this.to : this.from; } - /** - The head of the range, which is moved when the range is - [extended](https://codemirror.net/6/docs/ref/#state.SelectionRange.extend). - */ - get head() { return this.flags & 16 /* Inverted */ ? this.from : this.to; } - /** - True when `anchor` and `head` are at the same position. - */ - get empty() { return this.from == this.to; } - /** - If this is a cursor that is explicitly associated with the - character on one of its sides, this returns the side. -1 means - the character before its position, 1 the character after, and 0 - means no association. - */ - get assoc() { return this.flags & 4 /* AssocBefore */ ? -1 : this.flags & 8 /* AssocAfter */ ? 1 : 0; } - /** - The bidirectional text level associated with this cursor, if - any. - */ - get bidiLevel() { - let level = this.flags & 3 /* BidiLevelMask */; - return level == 3 ? null : level; - } - /** - The goal column (stored vertical offset) associated with a - cursor. This is used to preserve the vertical position when - [moving](https://codemirror.net/6/docs/ref/#view.EditorView.moveVertically) across - lines of different length. - */ - get goalColumn() { - let value = this.flags >> 5 /* GoalColumnOffset */; - return value == 33554431 /* NoGoalColumn */ ? undefined : value; - } - /** - Map this range through a change, producing a valid range in the - updated document. - */ - map(change, assoc = -1) { - let from = change.mapPos(this.from, assoc), to = change.mapPos(this.to, assoc); - return from == this.from && to == this.to ? this : new SelectionRange(from, to, this.flags); - } - /** - Extend this range to cover at least `from` to `to`. - */ - extend(from, to = from) { - if (from <= this.anchor && to >= this.anchor) - return EditorSelection.range(from, to); - let head = Math.abs(from - this.anchor) > Math.abs(to - this.anchor) ? from : to; - return EditorSelection.range(this.anchor, head); - } - /** - Compare this range to another range. - */ - eq(other) { - return this.anchor == other.anchor && this.head == other.head; - } - /** - Return a JSON-serializable object representing the range. - */ - toJSON() { return { anchor: this.anchor, head: this.head }; } - /** - Convert a JSON representation of a range to a `SelectionRange` - instance. - */ - static fromJSON(json) { - if (!json || typeof json.anchor != "number" || typeof json.head != "number") - throw new RangeError("Invalid JSON representation for SelectionRange"); - return EditorSelection.range(json.anchor, json.head); - } - } - /** - An editor selection holds one or more selection ranges. - */ - class EditorSelection { - /** - @internal - */ - constructor( - /** - The ranges in the selection, sorted by position. Ranges cannot - overlap (but they may touch, if they aren't empty). - */ - ranges, - /** - The index of the _main_ range in the selection (which is - usually the range that was added last). - */ - mainIndex = 0) { - this.ranges = ranges; - this.mainIndex = mainIndex; - } - /** - Map a selection through a change. Used to adjust the selection - position for changes. - */ - map(change, assoc = -1) { - if (change.empty) - return this; - return EditorSelection.create(this.ranges.map(r => r.map(change, assoc)), this.mainIndex); - } - /** - Compare this selection to another selection. - */ - eq(other) { - if (this.ranges.length != other.ranges.length || - this.mainIndex != other.mainIndex) - return false; - for (let i = 0; i < this.ranges.length; i++) - if (!this.ranges[i].eq(other.ranges[i])) - return false; - return true; - } - /** - Get the primary selection range. Usually, you should make sure - your code applies to _all_ ranges, by using methods like - [`changeByRange`](https://codemirror.net/6/docs/ref/#state.EditorState.changeByRange). - */ - get main() { return this.ranges[this.mainIndex]; } - /** - Make sure the selection only has one range. Returns a selection - holding only the main range from this selection. - */ - asSingle() { - return this.ranges.length == 1 ? this : new EditorSelection([this.main]); - } - /** - Extend this selection with an extra range. - */ - addRange(range, main = true) { - return EditorSelection.create([range].concat(this.ranges), main ? 0 : this.mainIndex + 1); - } - /** - Replace a given range with another range, and then normalize the - selection to merge and sort ranges if necessary. - */ - replaceRange(range, which = this.mainIndex) { - let ranges = this.ranges.slice(); - ranges[which] = range; - return EditorSelection.create(ranges, this.mainIndex); - } - /** - Convert this selection to an object that can be serialized to - JSON. - */ - toJSON() { - return { ranges: this.ranges.map(r => r.toJSON()), main: this.mainIndex }; - } - /** - Create a selection from a JSON representation. - */ - static fromJSON(json) { - if (!json || !Array.isArray(json.ranges) || typeof json.main != "number" || json.main >= json.ranges.length) - throw new RangeError("Invalid JSON representation for EditorSelection"); - return new EditorSelection(json.ranges.map((r) => SelectionRange.fromJSON(r)), json.main); - } - /** - Create a selection holding a single range. - */ - static single(anchor, head = anchor) { - return new EditorSelection([EditorSelection.range(anchor, head)], 0); - } - /** - Sort and merge the given set of ranges, creating a valid - selection. - */ - static create(ranges, mainIndex = 0) { - if (ranges.length == 0) - throw new RangeError("A selection needs at least one range"); - for (let pos = 0, i = 0; i < ranges.length; i++) { - let range = ranges[i]; - if (range.empty ? range.from <= pos : range.from < pos) - return normalized(ranges.slice(), mainIndex); - pos = range.to; - } - return new EditorSelection(ranges, mainIndex); - } - /** - Create a cursor selection range at the given position. You can - safely ignore the optional arguments in most situations. - */ - static cursor(pos, assoc = 0, bidiLevel, goalColumn) { - return new SelectionRange(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* AssocBefore */ : 8 /* AssocAfter */) | - (bidiLevel == null ? 3 : Math.min(2, bidiLevel)) | - ((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */)); - } - /** - Create a selection range. - */ - static range(anchor, head, goalColumn) { - let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* NoGoalColumn */) << 5 /* GoalColumnOffset */; - return head < anchor ? new SelectionRange(head, anchor, 16 /* Inverted */ | goal) : new SelectionRange(anchor, head, goal); - } - } - function normalized(ranges, mainIndex = 0) { - let main = ranges[mainIndex]; - ranges.sort((a, b) => a.from - b.from); - mainIndex = ranges.indexOf(main); - for (let i = 1; i < ranges.length; i++) { - let range = ranges[i], prev = ranges[i - 1]; - if (range.empty ? range.from <= prev.to : range.from < prev.to) { - let from = prev.from, to = Math.max(range.to, prev.to); - if (i <= mainIndex) - mainIndex--; - ranges.splice(--i, 2, range.anchor > range.head ? EditorSelection.range(to, from) : EditorSelection.range(from, to)); - } - } - return new EditorSelection(ranges, mainIndex); - } - function checkSelection(selection, docLength) { - for (let range of selection.ranges) - if (range.to > docLength) - throw new RangeError("Selection points outside of document"); - } - - let nextID = 0; - /** - A facet is a labeled value that is associated with an editor - state. It takes inputs from any number of extensions, and combines - those into a single output value. - - Examples of facets are the [theme](https://codemirror.net/6/docs/ref/#view.EditorView^theme) styles - associated with an editor or the [tab - size](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize) (which is reduced to a single - value, using the input with the hightest precedence). - */ - class Facet { - constructor( - /** - @internal - */ - combine, - /** - @internal - */ - compareInput, - /** - @internal - */ - compare, isStatic, - /** - @internal - */ - extensions) { - this.combine = combine; - this.compareInput = compareInput; - this.compare = compare; - this.isStatic = isStatic; - this.extensions = extensions; - /** - @internal - */ - this.id = nextID++; - this.default = combine([]); - } - /** - Define a new facet. - */ - static define(config = {}) { - return new Facet(config.combine || ((a) => a), config.compareInput || ((a, b) => a === b), config.compare || (!config.combine ? sameArray$1 : (a, b) => a === b), !!config.static, config.enables); - } - /** - Returns an extension that adds the given value for this facet. - */ - of(value) { - return new FacetProvider([], this, 0 /* Static */, value); - } - /** - Create an extension that computes a value for the facet from a - state. You must take care to declare the parts of the state that - this value depends on, since your function is only called again - for a new state when one of those parts changed. - - In most cases, you'll want to use the - [`provide`](https://codemirror.net/6/docs/ref/#state.StateField^define^config.provide) option when - defining a field instead. - */ - compute(deps, get) { - if (this.isStatic) - throw new Error("Can't compute a static facet"); - return new FacetProvider(deps, this, 1 /* Single */, get); - } - /** - Create an extension that computes zero or more values for this - facet from a state. - */ - computeN(deps, get) { - if (this.isStatic) - throw new Error("Can't compute a static facet"); - return new FacetProvider(deps, this, 2 /* Multi */, get); - } - from(field, get) { - if (!get) - get = x => x; - return this.compute([field], state => get(state.field(field))); - } - } - function sameArray$1(a, b) { - return a == b || a.length == b.length && a.every((e, i) => e === b[i]); - } - class FacetProvider { - constructor(dependencies, facet, type, value) { - this.dependencies = dependencies; - this.facet = facet; - this.type = type; - this.value = value; - this.id = nextID++; - } - dynamicSlot(addresses) { - var _a; - let getter = this.value; - let compare = this.facet.compareInput; - let idx = addresses[this.id] >> 1, multi = this.type == 2 /* Multi */; - let depDoc = false, depSel = false, depAddrs = []; - for (let dep of this.dependencies) { - if (dep == "doc") - depDoc = true; - else if (dep == "selection") - depSel = true; - else if ((((_a = addresses[dep.id]) !== null && _a !== void 0 ? _a : 1) & 1) == 0) - depAddrs.push(addresses[dep.id]); - } - return (state, tr) => { - if (!tr || tr.reconfigured) { - state.values[idx] = getter(state); - return 1 /* Changed */; - } - else { - let depChanged = (depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) || - depAddrs.some(addr => (ensureAddr(state, addr) & 1 /* Changed */) > 0); - if (!depChanged) - return 0; - let newVal = getter(state), oldVal = tr.startState.values[idx]; - if (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal)) - return 0; - state.values[idx] = newVal; - return 1 /* Changed */; - } - }; - } - } - function compareArray(a, b, compare) { - if (a.length != b.length) - return false; - for (let i = 0; i < a.length; i++) - if (!compare(a[i], b[i])) - return false; - return true; - } - function dynamicFacetSlot(addresses, facet, providers) { - let providerAddrs = providers.map(p => addresses[p.id]); - let providerTypes = providers.map(p => p.type); - let dynamic = providerAddrs.filter(p => !(p & 1)); - let idx = addresses[facet.id] >> 1; - return (state, tr) => { - let oldAddr = !tr ? null : tr.reconfigured ? tr.startState.config.address[facet.id] : idx << 1; - let changed = oldAddr == null; - for (let dynAddr of dynamic) { - if (ensureAddr(state, dynAddr) & 1 /* Changed */) - changed = true; - } - if (!changed) - return 0; - let values = []; - for (let i = 0; i < providerAddrs.length; i++) { - let value = getAddr(state, providerAddrs[i]); - if (providerTypes[i] == 2 /* Multi */) - for (let val of value) - values.push(val); - else - values.push(value); - } - let newVal = facet.combine(values); - if (oldAddr != null && facet.compare(newVal, getAddr(tr.startState, oldAddr))) - return 0; - state.values[idx] = newVal; - return 1 /* Changed */; - }; - } - function maybeIndex(state, id) { - let found = state.config.address[id]; - return found == null ? null : found >> 1; - } - const initField = Facet.define({ static: true }); - /** - Fields can store additional information in an editor state, and - keep it in sync with the rest of the state. - */ - class StateField { - constructor( - /** - @internal - */ - id, createF, updateF, compareF, - /** - @internal - */ - spec) { - this.id = id; - this.createF = createF; - this.updateF = updateF; - this.compareF = compareF; - this.spec = spec; - /** - @internal - */ - this.provides = undefined; - } - /** - Define a state field. - */ - static define(config) { - let field = new StateField(nextID++, config.create, config.update, config.compare || ((a, b) => a === b), config); - if (config.provide) - field.provides = config.provide(field); - return field; - } - create(state) { - let init = state.facet(initField).find(i => i.field == this); - return ((init === null || init === void 0 ? void 0 : init.create) || this.createF)(state); - } - /** - @internal - */ - slot(addresses) { - let idx = addresses[this.id] >> 1; - return (state, tr) => { - if (!tr) { - state.values[idx] = this.create(state); - return 1 /* Changed */; - } - let oldVal, changed = 0; - if (tr.reconfigured) { - let oldIdx = maybeIndex(tr.startState, this.id); - oldVal = oldIdx == null ? this.create(tr.startState) : tr.startState.values[oldIdx]; - changed = 1 /* Changed */; - } - else { - oldVal = tr.startState.values[idx]; - } - let value = this.updateF(oldVal, tr); - if (!changed && !this.compareF(oldVal, value)) - changed = 1 /* Changed */; - if (changed) - state.values[idx] = value; - return changed; - }; - } - /** - Returns an extension that enables this field and overrides the - way it is initialized. Can be useful when you need to provide a - non-default starting value for the field. - */ - init(create) { - return [this, initField.of({ field: this, create })]; - } - /** - State field instances can be used as - [`Extension`](https://codemirror.net/6/docs/ref/#state.Extension) values to enable the field in a - given state. - */ - get extension() { return this; } - } - const Prec_ = { fallback: 3, default: 2, extend: 1, override: 0 }; - function prec(value) { - return (ext) => new PrecExtension(ext, value); - } - /** - By default extensions are registered in the order they are found - in the flattened form of nested array that was provided. - Individual extension values can be assigned a precedence to - override this. Extensions that do not have a precedence set get - the precedence of the nearest parent with a precedence, or - [`default`](https://codemirror.net/6/docs/ref/#state.Prec.default) if there is no such parent. The - final ordering of extensions is determined by first sorting by - precedence and then by order within each precedence. - */ - const Prec = { - /** - A precedence below the default precedence, which will cause - default-precedence extensions to override it even if they are - specified later in the extension ordering. - */ - fallback: prec(Prec_.fallback), - /** - The regular default precedence. - */ - default: prec(Prec_.default), - /** - A higher-than-default precedence. - */ - extend: prec(Prec_.extend), - /** - Precedence above the `default` and `extend` precedences. - */ - override: prec(Prec_.override) - }; - class PrecExtension { - constructor(inner, prec) { - this.inner = inner; - this.prec = prec; - } - } - /** - Extension compartments can be used to make a configuration - dynamic. By [wrapping](https://codemirror.net/6/docs/ref/#state.Compartment.of) part of your - configuration in a compartment, you can later - [replace](https://codemirror.net/6/docs/ref/#state.Compartment.reconfigure) that part through a - transaction. - */ - class Compartment { - /** - Create an instance of this compartment to add to your [state - configuration](https://codemirror.net/6/docs/ref/#state.EditorStateConfig.extensions). - */ - of(ext) { return new CompartmentInstance(this, ext); } - /** - Create an [effect](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) that - reconfigures this compartment. - */ - reconfigure(content) { - return Compartment.reconfigure.of({ compartment: this, extension: content }); - } - /** - Get the current content of the compartment in the state, or - `undefined` if it isn't present. - */ - get(state) { - return state.config.compartments.get(this); - } - } - class CompartmentInstance { - constructor(compartment, inner) { - this.compartment = compartment; - this.inner = inner; - } - } - class Configuration { - constructor(base, compartments, dynamicSlots, address, staticValues) { - this.base = base; - this.compartments = compartments; - this.dynamicSlots = dynamicSlots; - this.address = address; - this.staticValues = staticValues; - this.statusTemplate = []; - while (this.statusTemplate.length < dynamicSlots.length) - this.statusTemplate.push(0 /* Uninitialized */); - } - staticFacet(facet) { - let addr = this.address[facet.id]; - return addr == null ? facet.default : this.staticValues[addr >> 1]; - } - static resolve(base, compartments, oldState) { - let fields = []; - let facets = Object.create(null); - let newCompartments = new Map(); - for (let ext of flatten(base, compartments, newCompartments)) { - if (ext instanceof StateField) - fields.push(ext); - else - (facets[ext.facet.id] || (facets[ext.facet.id] = [])).push(ext); - } - let address = Object.create(null); - let staticValues = []; - let dynamicSlots = []; - for (let field of fields) { - address[field.id] = dynamicSlots.length << 1; - dynamicSlots.push(a => field.slot(a)); - } - for (let id in facets) { - let providers = facets[id], facet = providers[0].facet; - if (providers.every(p => p.type == 0 /* Static */)) { - address[facet.id] = (staticValues.length << 1) | 1; - let value = facet.combine(providers.map(p => p.value)); - let oldAddr = oldState ? oldState.config.address[facet.id] : null; - if (oldAddr != null) { - let oldVal = getAddr(oldState, oldAddr); - if (facet.compare(value, oldVal)) - value = oldVal; - } - staticValues.push(value); - } - else { - for (let p of providers) { - if (p.type == 0 /* Static */) { - address[p.id] = (staticValues.length << 1) | 1; - staticValues.push(p.value); - } - else { - address[p.id] = dynamicSlots.length << 1; - dynamicSlots.push(a => p.dynamicSlot(a)); - } - } - address[facet.id] = dynamicSlots.length << 1; - dynamicSlots.push(a => dynamicFacetSlot(a, facet, providers)); - } - } - return new Configuration(base, newCompartments, dynamicSlots.map(f => f(address)), address, staticValues); - } - } - function flatten(extension, compartments, newCompartments) { - let result = [[], [], [], []]; - let seen = new Map(); - function inner(ext, prec) { - let known = seen.get(ext); - if (known != null) { - if (known >= prec) - return; - let found = result[known].indexOf(ext); - if (found > -1) - result[known].splice(found, 1); - if (ext instanceof CompartmentInstance) - newCompartments.delete(ext.compartment); - } - seen.set(ext, prec); - if (Array.isArray(ext)) { - for (let e of ext) - inner(e, prec); - } - else if (ext instanceof CompartmentInstance) { - if (newCompartments.has(ext.compartment)) - throw new RangeError(`Duplicate use of compartment in extensions`); - let content = compartments.get(ext.compartment) || ext.inner; - newCompartments.set(ext.compartment, content); - inner(content, prec); - } - else if (ext instanceof PrecExtension) { - inner(ext.inner, ext.prec); - } - else if (ext instanceof StateField) { - result[prec].push(ext); - if (ext.provides) - inner(ext.provides, prec); - } - else if (ext instanceof FacetProvider) { - result[prec].push(ext); - if (ext.facet.extensions) - inner(ext.facet.extensions, prec); - } - else { - let content = ext.extension; - if (!content) - throw new Error(`Unrecognized extension value in extension set (${ext}). This sometimes happens because multiple instances of @codemirror/state are loaded, breaking instanceof checks.`); - inner(content, prec); - } - } - inner(extension, Prec_.default); - return result.reduce((a, b) => a.concat(b)); - } - function ensureAddr(state, addr) { - if (addr & 1) - return 2 /* Computed */; - let idx = addr >> 1; - let status = state.status[idx]; - if (status == 4 /* Computing */) - throw new Error("Cyclic dependency between fields and/or facets"); - if (status & 2 /* Computed */) - return status; - state.status[idx] = 4 /* Computing */; - let changed = state.config.dynamicSlots[idx](state, state.applying); - return state.status[idx] = 2 /* Computed */ | changed; - } - function getAddr(state, addr) { - return addr & 1 ? state.config.staticValues[addr >> 1] : state.values[addr >> 1]; - } - - const languageData = Facet.define(); - const allowMultipleSelections = Facet.define({ - combine: values => values.some(v => v), - static: true - }); - const lineSeparator = Facet.define({ - combine: values => values.length ? values[0] : undefined, - static: true - }); - const changeFilter = Facet.define(); - const transactionFilter = Facet.define(); - const transactionExtender = Facet.define(); - - /** - Annotations are tagged values that are used to add metadata to - transactions in an extensible way. They should be used to model - things that effect the entire transaction (such as its [time - stamp](https://codemirror.net/6/docs/ref/#state.Transaction^time) or information about its - [origin](https://codemirror.net/6/docs/ref/#state.Transaction^userEvent)). For effects that happen - _alongside_ the other changes made by the transaction, [state - effects](https://codemirror.net/6/docs/ref/#state.StateEffect) are more appropriate. - */ - class Annotation { - /** - @internal - */ - constructor( - /** - The annotation type. - */ - type, - /** - The value of this annotation. - */ - value) { - this.type = type; - this.value = value; - } - /** - Define a new type of annotation. - */ - static define() { return new AnnotationType(); } - } - /** - Marker that identifies a type of [annotation](https://codemirror.net/6/docs/ref/#state.Annotation). - */ - class AnnotationType { - /** - Create an instance of this annotation. - */ - of(value) { return new Annotation(this, value); } - } - /** - Representation of a type of state effect. Defined with - [`StateEffect.define`](https://codemirror.net/6/docs/ref/#state.StateEffect^define). - */ - class StateEffectType { - /** - @internal - */ - constructor( - // The `any` types in these function types are there to work - // around TypeScript issue #37631, where the type guard on - // `StateEffect.is` mysteriously stops working when these properly - // have type `Value`. - /** - @internal - */ - map) { - this.map = map; - } - /** - Create a [state effect](https://codemirror.net/6/docs/ref/#state.StateEffect) instance of this - type. - */ - of(value) { return new StateEffect(this, value); } - } - /** - State effects can be used to represent additional effects - associated with a [transaction](https://codemirror.net/6/docs/ref/#state.Transaction.effects). They - are often useful to model changes to custom [state - fields](https://codemirror.net/6/docs/ref/#state.StateField), when those changes aren't implicit in - document or selection changes. - */ - class StateEffect { - /** - @internal - */ - constructor( - /** - @internal - */ - type, - /** - The value of this effect. - */ - value) { - this.type = type; - this.value = value; - } - /** - Map this effect through a position mapping. Will return - `undefined` when that ends up deleting the effect. - */ - map(mapping) { - let mapped = this.type.map(this.value, mapping); - return mapped === undefined ? undefined : mapped == this.value ? this : new StateEffect(this.type, mapped); - } - /** - Tells you whether this effect object is of a given - [type](https://codemirror.net/6/docs/ref/#state.StateEffectType). - */ - is(type) { return this.type == type; } - /** - Define a new effect type. The type parameter indicates the type - of values that his effect holds. - */ - static define(spec = {}) { - return new StateEffectType(spec.map || (v => v)); - } - /** - Map an array of effects through a change set. - */ - static mapEffects(effects, mapping) { - if (!effects.length) - return effects; - let result = []; - for (let effect of effects) { - let mapped = effect.map(mapping); - if (mapped) - result.push(mapped); - } - return result; - } - } - /** - This effect can be used to reconfigure the root extensions of - the editor. Doing this will discard any extensions - [appended](https://codemirror.net/6/docs/ref/#state.StateEffect^appendConfig), but does not reset - the content of [reconfigured](https://codemirror.net/6/docs/ref/#state.Compartment.reconfigure) - compartments. - */ - StateEffect.reconfigure = StateEffect.define(); - /** - Append extensions to the top-level configuration of the editor. - */ - StateEffect.appendConfig = StateEffect.define(); - /** - Changes to the editor state are grouped into transactions. - Typically, a user action creates a single transaction, which may - contain any number of document changes, may change the selection, - or have other effects. Create a transaction by calling - [`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update). - */ - class Transaction { - /** - @internal - */ - constructor( - /** - The state from which the transaction starts. - */ - startState, - /** - The document changes made by this transaction. - */ - changes, - /** - The selection set by this transaction, or undefined if it - doesn't explicitly set a selection. - */ - selection, - /** - The effects added to the transaction. - */ - effects, - /** - @internal - */ - annotations, - /** - Whether the selection should be scrolled into view after this - transaction is dispatched. - */ - scrollIntoView) { - this.startState = startState; - this.changes = changes; - this.selection = selection; - this.effects = effects; - this.annotations = annotations; - this.scrollIntoView = scrollIntoView; - /** - @internal - */ - this._doc = null; - /** - @internal - */ - this._state = null; - if (selection) - checkSelection(selection, changes.newLength); - if (!annotations.some((a) => a.type == Transaction.time)) - this.annotations = annotations.concat(Transaction.time.of(Date.now())); - } - /** - The new document produced by the transaction. Contrary to - [`.state`](https://codemirror.net/6/docs/ref/#state.Transaction.state)`.doc`, accessing this won't - force the entire new state to be computed right away, so it is - recommended that [transaction - filters](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter) use this getter - when they need to look at the new document. - */ - get newDoc() { - return this._doc || (this._doc = this.changes.apply(this.startState.doc)); - } - /** - The new selection produced by the transaction. If - [`this.selection`](https://codemirror.net/6/docs/ref/#state.Transaction.selection) is undefined, - this will [map](https://codemirror.net/6/docs/ref/#state.EditorSelection.map) the start state's - current selection through the changes made by the transaction. - */ - get newSelection() { - return this.selection || this.startState.selection.map(this.changes); - } - /** - The new state created by the transaction. Computed on demand - (but retained for subsequent access), so itis recommended not to - access it in [transaction - filters](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter) when possible. - */ - get state() { - if (!this._state) - this.startState.applyTransaction(this); - return this._state; - } - /** - Get the value of the given annotation type, if any. - */ - annotation(type) { - for (let ann of this.annotations) - if (ann.type == type) - return ann.value; - return undefined; - } - /** - Indicates whether the transaction changed the document. - */ - get docChanged() { return !this.changes.empty; } - /** - Indicates whether this transaction reconfigures the state - (through a [configuration compartment](https://codemirror.net/6/docs/ref/#state.Compartment) or - with a top-level configuration - [effect](https://codemirror.net/6/docs/ref/#state.StateEffect^reconfigure). - */ - get reconfigured() { return this.startState.config != this.state.config; } - } - /** - Annotation used to store transaction timestamps. - */ - Transaction.time = Annotation.define(); - /** - Annotation used to associate a transaction with a user interface - event. The view will set this to... - - - `"input"` when the user types text - - `"delete"` when the user deletes the selection or text near the selection - - `"keyboardselection"` when moving the selection via the keyboard - - `"pointerselection"` when moving the selection through the pointing device - - `"paste"` when pasting content - - `"cut"` when cutting - - `"drop"` when content is inserted via drag-and-drop - */ - Transaction.userEvent = Annotation.define(); - /** - Annotation indicating whether a transaction should be added to - the undo history or not. - */ - Transaction.addToHistory = Annotation.define(); - function joinRanges(a, b) { - let result = []; - for (let iA = 0, iB = 0;;) { - let from, to; - if (iA < a.length && (iB == b.length || b[iB] >= a[iA])) { - from = a[iA++]; - to = a[iA++]; - } - else if (iB < b.length) { - from = b[iB++]; - to = b[iB++]; - } - else - return result; - if (!result.length || result[result.length - 1] < from) - result.push(from, to); - else if (result[result.length - 1] < to) - result[result.length - 1] = to; - } - } - function mergeTransaction(a, b, sequential) { - var _a; - let mapForA, mapForB, changes; - if (sequential) { - mapForA = b.changes; - mapForB = ChangeSet.empty(b.changes.length); - changes = a.changes.compose(b.changes); - } - else { - mapForA = b.changes.map(a.changes); - mapForB = a.changes.mapDesc(b.changes, true); - changes = a.changes.compose(mapForA); - } - return { - changes, - selection: b.selection ? b.selection.map(mapForB) : (_a = a.selection) === null || _a === void 0 ? void 0 : _a.map(mapForA), - effects: StateEffect.mapEffects(a.effects, mapForA).concat(StateEffect.mapEffects(b.effects, mapForB)), - annotations: a.annotations.length ? a.annotations.concat(b.annotations) : b.annotations, - scrollIntoView: a.scrollIntoView || b.scrollIntoView - }; - } - function resolveTransactionInner(state, spec, docSize) { - let sel = spec.selection; - return { - changes: spec.changes instanceof ChangeSet ? spec.changes - : ChangeSet.of(spec.changes || [], docSize, state.facet(lineSeparator)), - selection: sel && (sel instanceof EditorSelection ? sel : EditorSelection.single(sel.anchor, sel.head)), - effects: asArray(spec.effects), - annotations: asArray(spec.annotations), - scrollIntoView: !!spec.scrollIntoView - }; - } - function resolveTransaction(state, specs, filter) { - let s = resolveTransactionInner(state, specs.length ? specs[0] : {}, state.doc.length); - if (specs.length && specs[0].filter === false) - filter = false; - for (let i = 1; i < specs.length; i++) { - if (specs[i].filter === false) - filter = false; - let seq = !!specs[i].sequential; - s = mergeTransaction(s, resolveTransactionInner(state, specs[i], seq ? s.changes.newLength : state.doc.length), seq); - } - let tr = new Transaction(state, s.changes, s.selection, s.effects, s.annotations, s.scrollIntoView); - return extendTransaction(filter ? filterTransaction(tr) : tr); - } - // Finish a transaction by applying filters if necessary. - function filterTransaction(tr) { - let state = tr.startState; - // Change filters - let result = true; - for (let filter of state.facet(changeFilter)) { - let value = filter(tr); - if (value === false) { - result = false; - break; - } - if (Array.isArray(value)) - result = result === true ? value : joinRanges(result, value); - } - if (result !== true) { - let changes, back; - if (result === false) { - back = tr.changes.invertedDesc; - changes = ChangeSet.empty(state.doc.length); - } - else { - let filtered = tr.changes.filter(result); - changes = filtered.changes; - back = filtered.filtered.invertedDesc; - } - tr = new Transaction(state, changes, tr.selection && tr.selection.map(back), StateEffect.mapEffects(tr.effects, back), tr.annotations, tr.scrollIntoView); - } - // Transaction filters - let filters = state.facet(transactionFilter); - for (let i = filters.length - 1; i >= 0; i--) { - let filtered = filters[i](tr); - if (filtered instanceof Transaction) - tr = filtered; - else if (Array.isArray(filtered) && filtered.length == 1 && filtered[0] instanceof Transaction) - tr = filtered[0]; - else - tr = resolveTransaction(state, asArray(filtered), false); - } - return tr; - } - function extendTransaction(tr) { - let state = tr.startState, extenders = state.facet(transactionExtender), spec = tr; - for (let i = extenders.length - 1; i >= 0; i--) { - let extension = extenders[i](tr); - if (extension && Object.keys(extension).length) - spec = mergeTransaction(tr, resolveTransactionInner(state, extension, tr.changes.newLength), true); - } - return spec == tr ? tr : new Transaction(state, tr.changes, tr.selection, spec.effects, spec.annotations, spec.scrollIntoView); - } - const none$5 = []; - function asArray(value) { - return value == null ? none$5 : Array.isArray(value) ? value : [value]; - } - - /** - The categories produced by a [character - categorizer](https://codemirror.net/6/docs/ref/#state.EditorState.charCategorizer). These are used - do things like selecting by word. - */ - var CharCategory; - (function (CharCategory) { - /** - Word characters. - */ - CharCategory[CharCategory["Word"] = 0] = "Word"; - /** - Whitespace. - */ - CharCategory[CharCategory["Space"] = 1] = "Space"; - /** - Anything else. - */ - CharCategory[CharCategory["Other"] = 2] = "Other"; - })(CharCategory || (CharCategory = {})); - const nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; - let wordChar; - try { - wordChar = new RegExp("[\\p{Alphabetic}\\p{Number}_]", "u"); - } - catch (_) { } - function hasWordChar(str) { - if (wordChar) - return wordChar.test(str); - for (let i = 0; i < str.length; i++) { - let ch = str[i]; - if (/\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))) - return true; - } - return false; - } - function makeCategorizer(wordChars) { - return (char) => { - if (!/\S/.test(char)) - return CharCategory.Space; - if (hasWordChar(char)) - return CharCategory.Word; - for (let i = 0; i < wordChars.length; i++) - if (char.indexOf(wordChars[i]) > -1) - return CharCategory.Word; - return CharCategory.Other; - }; - } - - /** - The editor state class is a persistent (immutable) data structure. - To update a state, you [create](https://codemirror.net/6/docs/ref/#state.EditorState.update) a - [transaction](https://codemirror.net/6/docs/ref/#state.Transaction), which produces a _new_ state - instance, without modifying the original object. - - As such, _never_ mutate properties of a state directly. That'll - just break things. - */ - class EditorState { - /** - @internal - */ - constructor( - /** - @internal - */ - config, - /** - The current document. - */ - doc, - /** - The current selection. - */ - selection, tr = null) { - this.config = config; - this.doc = doc; - this.selection = selection; - /** - @internal - */ - this.applying = null; - this.status = config.statusTemplate.slice(); - if (tr && tr.startState.config == config) { - this.values = tr.startState.values.slice(); - } - else { - this.values = config.dynamicSlots.map(_ => null); - // Copy over old values for shared facets/fields if this is a reconfigure - if (tr) - for (let id in config.address) { - let cur = config.address[id], prev = tr.startState.config.address[id]; - if (prev != null && (cur & 1) == 0) - this.values[cur >> 1] = getAddr(tr.startState, prev); - } - } - this.applying = tr; - // Fill in the computed state immediately, so that further queries - // for it made during the update return this state - if (tr) - tr._state = this; - for (let i = 0; i < this.config.dynamicSlots.length; i++) - ensureAddr(this, i << 1); - this.applying = null; - } - field(field, require = true) { - let addr = this.config.address[field.id]; - if (addr == null) { - if (require) - throw new RangeError("Field is not present in this state"); - return undefined; - } - ensureAddr(this, addr); - return getAddr(this, addr); - } - /** - Create a [transaction](https://codemirror.net/6/docs/ref/#state.Transaction) that updates this - state. Any number of [transaction specs](https://codemirror.net/6/docs/ref/#state.TransactionSpec) - can be passed. Unless - [`sequential`](https://codemirror.net/6/docs/ref/#state.TransactionSpec.sequential) is set, the - [changes](https://codemirror.net/6/docs/ref/#state.TransactionSpec.changes) (if any) of each spec - are assumed to start in the _current_ document (not the document - produced by previous specs), and its - [selection](https://codemirror.net/6/docs/ref/#state.TransactionSpec.selection) and - [effects](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects) are assumed to refer - to the document created by its _own_ changes. The resulting - transaction contains the combined effect of all the different - specs. For [selection](https://codemirror.net/6/docs/ref/#state.TransactionSpec.selection), later - specs take precedence over earlier ones. - */ - update(...specs) { - return resolveTransaction(this, specs, true); - } - /** - @internal - */ - applyTransaction(tr) { - let conf = this.config, { base, compartments } = conf; - for (let effect of tr.effects) { - if (effect.is(Compartment.reconfigure)) { - if (conf) { - compartments = new Map; - conf.compartments.forEach((val, key) => compartments.set(key, val)); - conf = null; - } - compartments.set(effect.value.compartment, effect.value.extension); - } - else if (effect.is(StateEffect.reconfigure)) { - conf = null; - base = effect.value; - } - else if (effect.is(StateEffect.appendConfig)) { - conf = null; - base = asArray(base).concat(effect.value); - } - } - new EditorState(conf || Configuration.resolve(base, compartments, this), tr.newDoc, tr.newSelection, tr); - } - /** - Create a [transaction spec](https://codemirror.net/6/docs/ref/#state.TransactionSpec) that - replaces every selection range with the given content. - */ - replaceSelection(text) { - if (typeof text == "string") - text = this.toText(text); - return this.changeByRange(range => ({ changes: { from: range.from, to: range.to, insert: text }, - range: EditorSelection.cursor(range.from + text.length) })); - } - /** - Create a set of changes and a new selection by running the given - function for each range in the active selection. The function - can return an optional set of changes (in the coordinate space - of the start document), plus an updated range (in the coordinate - space of the document produced by the call's own changes). This - method will merge all the changes and ranges into a single - changeset and selection, and return it as a [transaction - spec](https://codemirror.net/6/docs/ref/#state.TransactionSpec), which can be passed to - [`update`](https://codemirror.net/6/docs/ref/#state.EditorState.update). - */ - changeByRange(f) { - let sel = this.selection; - let result1 = f(sel.ranges[0]); - let changes = this.changes(result1.changes), ranges = [result1.range]; - let effects = asArray(result1.effects); - for (let i = 1; i < sel.ranges.length; i++) { - let result = f(sel.ranges[i]); - let newChanges = this.changes(result.changes), newMapped = newChanges.map(changes); - for (let j = 0; j < i; j++) - ranges[j] = ranges[j].map(newMapped); - let mapBy = changes.mapDesc(newChanges, true); - ranges.push(result.range.map(mapBy)); - changes = changes.compose(newMapped); - effects = StateEffect.mapEffects(effects, newMapped).concat(StateEffect.mapEffects(asArray(result.effects), mapBy)); - } - return { - changes, - selection: EditorSelection.create(ranges, sel.mainIndex), - effects - }; - } - /** - Create a [change set](https://codemirror.net/6/docs/ref/#state.ChangeSet) from the given change - description, taking the state's document length and line - separator into account. - */ - changes(spec = []) { - if (spec instanceof ChangeSet) - return spec; - return ChangeSet.of(spec, this.doc.length, this.facet(EditorState.lineSeparator)); - } - /** - Using the state's [line - separator](https://codemirror.net/6/docs/ref/#state.EditorState^lineSeparator), create a - [`Text`](https://codemirror.net/6/docs/ref/#text.Text) instance from the given string. - */ - toText(string) { - return Text.of(string.split(this.facet(EditorState.lineSeparator) || DefaultSplit)); - } - /** - Return the given range of the document as a string. - */ - sliceDoc(from = 0, to = this.doc.length) { - return this.doc.sliceString(from, to, this.lineBreak); - } - /** - Get the value of a state [facet](https://codemirror.net/6/docs/ref/#state.Facet). - */ - facet(facet) { - let addr = this.config.address[facet.id]; - if (addr == null) - return facet.default; - ensureAddr(this, addr); - return getAddr(this, addr); - } - /** - Convert this state to a JSON-serializable object. When custom - fields should be serialized, you can pass them in as an object - mapping property names (in the resulting object, which should - not use `doc` or `selection`) to fields. - */ - toJSON(fields) { - let result = { - doc: this.sliceDoc(), - selection: this.selection.toJSON() - }; - if (fields) - for (let prop in fields) { - let value = fields[prop]; - if (value instanceof StateField) - result[prop] = value.spec.toJSON(this.field(fields[prop]), this); - } - return result; - } - /** - Deserialize a state from its JSON representation. When custom - fields should be deserialized, pass the same object you passed - to [`toJSON`](https://codemirror.net/6/docs/ref/#state.EditorState.toJSON) when serializing as - third argument. - */ - static fromJSON(json, config = {}, fields) { - if (!json || typeof json.doc != "string") - throw new RangeError("Invalid JSON representation for EditorState"); - let fieldInit = []; - if (fields) - for (let prop in fields) { - let field = fields[prop], value = json[prop]; - fieldInit.push(field.init(state => field.spec.fromJSON(value, state))); - } - return EditorState.create({ - doc: json.doc, - selection: EditorSelection.fromJSON(json.selection), - extensions: config.extensions ? fieldInit.concat([config.extensions]) : fieldInit - }); - } - /** - Create a new state. You'll usually only need this when - initializing an editor—updated states are created by applying - transactions. - */ - static create(config = {}) { - let configuration = Configuration.resolve(config.extensions || [], new Map); - let doc = config.doc instanceof Text ? config.doc - : Text.of((config.doc || "").split(configuration.staticFacet(EditorState.lineSeparator) || DefaultSplit)); - let selection = !config.selection ? EditorSelection.single(0) - : config.selection instanceof EditorSelection ? config.selection - : EditorSelection.single(config.selection.anchor, config.selection.head); - checkSelection(selection, doc.length); - if (!configuration.staticFacet(allowMultipleSelections)) - selection = selection.asSingle(); - return new EditorState(configuration, doc, selection); - } - /** - The size (in columns) of a tab in the document, determined by - the [`tabSize`](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize) facet. - */ - get tabSize() { return this.facet(EditorState.tabSize); } - /** - Get the proper [line-break](https://codemirror.net/6/docs/ref/#state.EditorState^lineSeparator) - string for this state. - */ - get lineBreak() { return this.facet(EditorState.lineSeparator) || "\n"; } - /** - Look up a translation for the given phrase (via the - [`phrases`](https://codemirror.net/6/docs/ref/#state.EditorState^phrases) facet), or return the - original string if no translation is found. - */ - phrase(phrase) { - for (let map of this.facet(EditorState.phrases)) - if (Object.prototype.hasOwnProperty.call(map, phrase)) - return map[phrase]; - return phrase; - } - /** - Find the values for a given language data field, provided by the - the [`languageData`](https://codemirror.net/6/docs/ref/#state.EditorState^languageData) facet. - */ - languageDataAt(name, pos) { - let values = []; - for (let provider of this.facet(languageData)) { - for (let result of provider(this, pos)) { - if (Object.prototype.hasOwnProperty.call(result, name)) - values.push(result[name]); - } - } - return values; - } - /** - Return a function that can categorize strings (expected to - represent a single [grapheme cluster](https://codemirror.net/6/docs/ref/#text.findClusterBreak)) - into one of: - - - Word (contains an alphanumeric character or a character - explicitly listed in the local language's `"wordChars"` - language data, which should be a string) - - Space (contains only whitespace) - - Other (anything else) - */ - charCategorizer(at) { - return makeCategorizer(this.languageDataAt("wordChars", at).join("")); - } - } - /** - A facet that, when enabled, causes the editor to allow multiple - ranges to be selected. Be careful though, because by default the - editor relies on the native DOM selection, which cannot handle - multiple selections. An extension like - [`drawSelection`](https://codemirror.net/6/docs/ref/#view.drawSelection) can be used to make - secondary selections visible to the user. - */ - EditorState.allowMultipleSelections = allowMultipleSelections; - /** - Configures the tab size to use in this state. The first - (highest-precedence) value of the facet is used. If no value is - given, this defaults to 4. - */ - EditorState.tabSize = Facet.define({ - combine: values => values.length ? values[0] : 4 - }); - /** - The line separator to use. By default, any of `"\n"`, `"\r\n"` - and `"\r"` is treated as a separator when splitting lines, and - lines are joined with `"\n"`. - - When you configure a value here, only that precise separator - will be used, allowing you to round-trip documents through the - editor without normalizing line separators. - */ - EditorState.lineSeparator = lineSeparator; - /** - Registers translation phrases. The - [`phrase`](https://codemirror.net/6/docs/ref/#state.EditorState.phrase) method will look through - all objects registered with this facet to find translations for - its argument. - */ - EditorState.phrases = Facet.define(); - /** - A facet used to register [language - data](https://codemirror.net/6/docs/ref/#state.EditorState.languageDataAt) providers. - */ - EditorState.languageData = languageData; - /** - Facet used to register change filters, which are called for each - transaction (unless explicitly - [disabled](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter)), and can suppress - part of the transaction's changes. - - Such a function can return `true` to indicate that it doesn't - want to do anything, `false` to completely stop the changes in - the transaction, or a set of ranges in which changes should be - suppressed. Such ranges are represented as an array of numbers, - with each pair of two number indicating the start and end of a - range. So for example `[10, 20, 100, 110]` suppresses changes - between 10 and 20, and between 100 and 110. - */ - EditorState.changeFilter = changeFilter; - /** - Facet used to register a hook that gets a chance to update or - replace transaction specs before they are applied. This will - only be applied for transactions that don't have - [`filter`](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter) set to `false`. You - can either return a single (possibly the input transaction), or - an array of specs (which will be combined in the same way as the - arguments to [`EditorState.update`](https://codemirror.net/6/docs/ref/#state.EditorState.update)). - - When possible, it is recommended to avoid accessing - [`Transaction.state`](https://codemirror.net/6/docs/ref/#state.Transaction.state) in a filter, - since it will force creation of a state that will then be - discarded again, if the transaction is actually filtered. - - (This functionality should be used with care. Indiscriminately - modifying transaction is likely to break something or degrade - the user experience.) - */ - EditorState.transactionFilter = transactionFilter; - /** - This is a more limited form of - [`transactionFilter`](https://codemirror.net/6/docs/ref/#state.EditorState^transactionFilter), - which can only add - [annotations](https://codemirror.net/6/docs/ref/#state.TransactionSpec.annotations) and - [effects](https://codemirror.net/6/docs/ref/#state.TransactionSpec.effects). _But_, this type - of filter runs even the transaction has disabled regular - [filtering](https://codemirror.net/6/docs/ref/#state.TransactionSpec.filter), making it suitable - for effects that don't need to touch the changes or selection, - but do want to process every transaction. - - Extenders run _after_ filters, when both are applied. - */ - EditorState.transactionExtender = transactionExtender; - Compartment.reconfigure = StateEffect.define(); - - /** - Utility function for combining behaviors to fill in a config - object from an array of provided configs. Will, by default, error - when a field gets two values that aren't `===`-equal, but you can - provide combine functions per field to do something else. - */ - function combineConfig(configs, defaults, // Should hold only the optional properties of Config, but I haven't managed to express that - combine = {}) { - let result = {}; - for (let config of configs) - for (let key of Object.keys(config)) { - let value = config[key], current = result[key]; - if (current === undefined) - result[key] = value; - else if (current === value || value === undefined) ; // No conflict - else if (Object.hasOwnProperty.call(combine, key)) - result[key] = combine[key](current, value); - else - throw new Error("Config merge conflict for field " + key); - } - for (let key in defaults) - if (result[key] === undefined) - result[key] = defaults[key]; - return result; - } - - const C = "\u037c"; - const COUNT = typeof Symbol == "undefined" ? "__" + C : Symbol.for(C); - const SET = typeof Symbol == "undefined" ? "__styleSet" + Math.floor(Math.random() * 1e8) : Symbol("styleSet"); - const top = typeof globalThis != "undefined" ? globalThis : typeof window != "undefined" ? window : {}; - - // :: - Style modules encapsulate a set of CSS rules defined from - // JavaScript. Their definitions are only available in a given DOM - // root after it has been _mounted_ there with `StyleModule.mount`. - // - // Style modules should be created once and stored somewhere, as - // opposed to re-creating them every time you need them. The amount of - // CSS rules generated for a given DOM root is bounded by the amount - // of style modules that were used. So to avoid leaking rules, don't - // create these dynamically, but treat them as one-time allocations. - class StyleModule { - // :: (Object