From ef951c971db0e8ad87cc747eade69ac8c1af80d1 Mon Sep 17 00:00:00 2001 From: Margaret <62753112+meg-1@users.noreply.github.com> Date: Sat, 25 Mar 2023 15:46:59 +0200 Subject: [PATCH 1/3] adding a contacts web application example --- .../contacts_web_application/contacts.js | 57 + .../contacts_web_application/contacts.py | 42 + .../contacts_web_application/index.html | 136 + .../contacts_web_application/index.md | 10 + .../contacts_web_application/py_config.toml | 4 + .../contacts_web_application/pyscript.js | 27253 ++++++++++++++++ .../contacts_web_application/styles.css | 147 + 7 files changed, 27649 insertions(+) create mode 100644 src/psc/gallery/examples/contacts_web_application/contacts.js create mode 100644 src/psc/gallery/examples/contacts_web_application/contacts.py create mode 100644 src/psc/gallery/examples/contacts_web_application/index.html create mode 100644 src/psc/gallery/examples/contacts_web_application/index.md create mode 100644 src/psc/gallery/examples/contacts_web_application/py_config.toml create mode 100644 src/psc/gallery/examples/contacts_web_application/pyscript.js create mode 100644 src/psc/gallery/examples/contacts_web_application/styles.css diff --git a/src/psc/gallery/examples/contacts_web_application/contacts.js b/src/psc/gallery/examples/contacts_web_application/contacts.js new file mode 100644 index 0000000..4442cbe --- /dev/null +++ b/src/psc/gallery/examples/contacts_web_application/contacts.js @@ -0,0 +1,57 @@ +document.getElementById("search_area").addEventListener("input", function (user_input) { + const contacts_match_name_list = pyscript.runtime.globals.get('search_by_value') || "empty"; + if (user_input.target.value != "") { + const search_result = contacts_match_name_list(user_input.target.value); + } else { + clear_search_area(); + } + + return user_input.target.value; +}); + +function clear_search_area() { + const output_grid = document.getElementById("found_contacts_list"); + /* this function is for the search OUTPUT */ + output_grid.innerHTML = ""; +} + +function add_found_contact(contact_name, contact_number) { + const output_grid = document.getElementById("found_contacts_list"); + const contact_card = document.getElementById("contact_card_template").cloneNode(true); + contact_card.childNodes.forEach(function (child, number) { + if (child.className != undefined && + child.className.includes("name_template")) { + child.innerText = contact_name; + } + + if (child.className != undefined && + child.className.includes("number_template")) { + child.innerText = contact_number; + } + }); + + contact_card.style = "visibility: visible;"; + output_grid.appendChild(contact_card); + } + + function add_to_list(contact_number, contact_name) { + let grid = document.getElementById("contacts_list_grid"); + let contacts_card = document.createElement("div"); + contacts_card.className = "d-flex justify-content-center w-100 row contact_card"; + let name = document.createElement("span"); + name.className = "d-flex justify-content-center w-50 m-auto"; + contacts_card.style = "border: 1px solid black"; + //vertical-align: middle; + //align-middle + let num = document.createElement("span"); + num.className = "d-flex justify-content-center m-auto"; + num.innerHTML = contact_number; + name.innerHTML = contact_name; + //contacts_card.style = "background-color: green; width: 100%; height: 100px;"; + //contacts_card.id = "contacts_list_grid" + //contacts_card.innerHTML = contact_number + "
" + contact_name; + contacts_card.appendChild(name); + contacts_card.appendChild(num); + grid.appendChild(contacts_card); + } +//# sourceMappingURL=pyscript.js.map \ No newline at end of file diff --git a/src/psc/gallery/examples/contacts_web_application/contacts.py b/src/psc/gallery/examples/contacts_web_application/contacts.py new file mode 100644 index 0000000..9971296 --- /dev/null +++ b/src/psc/gallery/examples/contacts_web_application/contacts.py @@ -0,0 +1,42 @@ +""" Contacts Web Application """ +from js import add_to_list, clear_search_area, add_found_contact +import re +contacts_list = {} +output = Element("output") + +search_res = [] + +def search_by_value(query): + global search_res + search_res = [] + clear_search_area() + for number, name in contacts_list.items(): + temp = re.findall(query, name) + if temp: + contact = {"contact_name": name, "contact_number": number} + add_found_contact(name, number) + search_res.append(contact) + return search_res + +def contact_book(*args, **kwargs): + """Contact book function.""" + # Signal that PyScript is alive by setting the ``Save Contact`` + # disabled attribute + save_button = Element("save") + # Now get the various inputs + contact_name = Element("contact_name").value + phone_number = Element("phone_number").value + + if phone_number not in contacts_list.keys(): + contacts_list[phone_number] = contact_name + last_val = list(contacts_list.keys())[-1] + add_to_list(str(last_val), str(contacts_list[last_val])) + + +def setup(): + """When Pyodide starts up, enable the Save button.""" + save_button = Element("save") # noqa + save_button.element.removeAttribute("disabled") + output = Element("output") + +setup() \ No newline at end of file diff --git a/src/psc/gallery/examples/contacts_web_application/index.html b/src/psc/gallery/examples/contacts_web_application/index.html new file mode 100644 index 0000000..5e3928c --- /dev/null +++ b/src/psc/gallery/examples/contacts_web_application/index.html @@ -0,0 +1,136 @@ + + + + + + Contact Book + + + + + + + + +
+
+ +
+
+ +
+ +
+
+
+

+

Welcome to the "PyScript Contacts Web Application"
+ "how does it work?" +
    +
  • enter a contact name and number in the form area
  • +
  • click the "save contact" button
  • +
  • you will see the contact appear in the "name" and "number" area
  • +
  • enter as many contacts as you wish
  • +
  • + after adding one or more contacts, you can enter a query in the "enter your query" + area. this area is used as a search box. you can enter contact names, and easily find + the contacts name and number combined! +
  • +
  • Have fun!
  • +
+

+
+
+
+
+
+
Add Your Contacts
+ +
+
+ + +

+ +

+ + +
+ +
+
+
+ +
+
Search Box
+ + +
+
+
+
+ +
+

Contacts List

+
+

name

+

number

+
+
+ + +
+ +
+ + + + + +
+
+ + + + + + diff --git a/src/psc/gallery/examples/contacts_web_application/index.md b/src/psc/gallery/examples/contacts_web_application/index.md new file mode 100644 index 0000000..78039d5 --- /dev/null +++ b/src/psc/gallery/examples/contacts_web_application/index.md @@ -0,0 +1,10 @@ +--- +title: PyScript Contacts Web Application +subtitle: Enter some contacts, get some contacts. +author: meg-1 +linked_files: + - contacts.py + - styles.css +--- +The *body* description. +this project is intended to show interaction between Pyscript and JavaScript \ No newline at end of file diff --git a/src/psc/gallery/examples/contacts_web_application/py_config.toml b/src/psc/gallery/examples/contacts_web_application/py_config.toml new file mode 100644 index 0000000..c83c741 --- /dev/null +++ b/src/psc/gallery/examples/contacts_web_application/py_config.toml @@ -0,0 +1,4 @@ +autoclose_loader = true + +[[runtimes]] +src = "https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js" \ No newline at end of file diff --git a/src/psc/gallery/examples/contacts_web_application/pyscript.js b/src/psc/gallery/examples/contacts_web_application/pyscript.js new file mode 100644 index 0000000..f5ea08b --- /dev/null +++ b/src/psc/gallery/examples/contacts_web_application/pyscript.js @@ -0,0 +1,27253 @@ +var pyscript = (function (exports) { + 'use strict'; + + /* eslint-disable */ + !(function (r) { + if ('object' == typeof exports && 'undefined' != typeof module) module.exports = r(); + else if ('function' == typeof define && define.amd) define([], r); + else { + ('undefined' != typeof window + ? window + : 'undefined' != typeof global + ? global + : 'undefined' != typeof self + ? self + : this + ).toml = r(); + } + })(function () { + return (function r(t, e, n) { + function u(i, a) { + if (!e[i]) { + if (!t[i]) { + var c = 'function' == typeof require && require; + if (!a && c) return c(i, !0); + if (o) return o(i, !0); + var f = new Error("Cannot find module '" + i + "'"); + throw ((f.code = 'MODULE_NOT_FOUND'), f); + } + var s = (e[i] = { + exports: {}, + }); + t[i][0].call( + s.exports, + function (r) { + var e = t[i][1][r]; + return u(e || r); + }, + s, + s.exports, + r, + t, + e, + n, + ); + } + return e[i].exports; + } + for (var o = 'function' == typeof require && require, i = 0; i < n.length; i++) u(n[i]); + return u; + })( + { + 1: [ + function (r, t, e) { + t.exports = (function () { + + function r(t, e, n, u) { + (this.message = t), + (this.expected = e), + (this.found = n), + (this.location = u), + (this.name = 'SyntaxError'), + 'function' == typeof Error.captureStackTrace && Error.captureStackTrace(this, r); + } + return ( + (function (r, t) { + function e() { + this.constructor = r; + } + (e.prototype = t.prototype), (r.prototype = new e()); + })(r, Error), + (r.buildMessage = function (r, t) { + function e(r) { + return r.charCodeAt(0).toString(16).toUpperCase(); + } + + function n(r) { + return r + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function (r) { + return '\\x0' + e(r); + }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function (r) { + return '\\x' + e(r); + }); + } + + function u(r) { + return r + .replace(/\\/g, '\\\\') + .replace(/\]/g, '\\]') + .replace(/\^/g, '\\^') + .replace(/-/g, '\\-') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function (r) { + return '\\x0' + e(r); + }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function (r) { + return '\\x' + e(r); + }); + } + + function o(r) { + return i[r.type](r); + } + var i = { + literal: function (r) { + return '"' + n(r.text) + '"'; + }, + class: function (r) { + var t, + e = ''; + for (t = 0; t < r.parts.length; t++) + e += + r.parts[t] instanceof Array + ? u(r.parts[t][0]) + '-' + u(r.parts[t][1]) + : u(r.parts[t]); + return '[' + (r.inverted ? '^' : '') + e + ']'; + }, + any: function (r) { + return 'any character'; + }, + end: function (r) { + return 'end of input'; + }, + other: function (r) { + return r.description; + }, + }; + return ( + 'Expected ' + + (function (r) { + var t, + e, + n = new Array(r.length); + for (t = 0; t < r.length; t++) n[t] = o(r[t]); + if ((n.sort(), n.length > 0)) { + for (t = 1, e = 1; t < n.length; t++) + n[t - 1] !== n[t] && ((n[e] = n[t]), e++); + n.length = e; + } + switch (n.length) { + case 1: + return n[0]; + case 2: + return n[0] + ' or ' + n[1]; + default: + return n.slice(0, -1).join(', ') + ', or ' + n[n.length - 1]; + } + })(r) + + ' but ' + + (function (r) { + return r ? '"' + n(r) + '"' : 'end of input'; + })(t) + + ' found.' + ); + }), + { + SyntaxError: r, + parse: function (t, e) { + function n() { + return t.substring(Me, _e); + } + + function u(r, t) { + throw ((t = void 0 !== t ? t : f(Me, _e)), l(r, t)); + } + + function o(r, t) { + return { + type: 'literal', + text: r, + ignoreCase: t, + }; + } + + function i(r, t, e) { + return { + type: 'class', + parts: r, + inverted: t, + ignoreCase: e, + }; + } + + function a(r) { + return { + type: 'other', + description: r, + }; + } + + function c(r) { + var e, + n = Ne[r]; + if (n) return n; + for (e = r - 1; !Ne[e]; ) e--; + for ( + n = { + line: (n = Ne[e]).line, + column: n.column, + }; + e < r; + + ) + 10 === t.charCodeAt(e) ? (n.line++, (n.column = 1)) : n.column++, e++; + return (Ne[r] = n), n; + } + + function f(r, t) { + var e = c(r), + n = c(t); + return { + start: { + offset: r, + line: e.line, + column: e.column, + }, + end: { + offset: t, + line: n.line, + column: n.column, + }, + }; + } + + function s(r) { + _e < He || (_e > He && ((He = _e), (Ue = [])), Ue.push(r)); + } + + function l(t, e) { + return new r(t, null, null, e); + } + + function h(t, e, n) { + return new r(r.buildMessage(t, e), t, e, n); + } + + function p() { + var r, t, e, n, u, o, i, a; + for ( + r = _e, t = [], (e = g()) === mr && (e = d()) === mr && (e = A()); + e !== mr; + + ) + t.push(e), (e = g()) === mr && (e = d()) === mr && (e = A()); + if (t !== mr) { + if (((e = _e), (n = v()) !== mr)) { + for (u = [], (o = g()) === mr && (o = A()); o !== mr; ) + u.push(o), (o = g()) === mr && (o = A()); + u !== mr + ? ((o = _e), + (i = d()) !== mr && (a = p()) !== mr + ? (o = i = [i, a]) + : ((_e = o), (o = mr)), + o === mr && (o = null), + o !== mr ? (e = n = [n, u, o]) : ((_e = e), (e = mr))) + : ((_e = e), (e = mr)); + } else (_e = e), (e = mr); + e === mr && (e = null), + e !== mr ? ((Me = r), (r = t = wr())) : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return r; + } + + function v() { + var r, t; + return ( + (r = _e), + (t = Cr()) !== mr && ((Me = r), (t = Fr(t))), + (r = t) === mr && + ((r = _e), + (t = yr()) !== mr && ((Me = r), (t = Er(t))), + (r = t) === mr && + ((r = _e), (t = C()) !== mr && ((Me = r), (t = Tr(t))), (r = t))), + r + ); + } + + function d() { + var r; + return ( + Ze++, + 10 === t.charCodeAt(_e) ? ((r = Or), _e++) : ((r = mr), 0 === Ze && s(jr)), + r === mr && + (t.substr(_e, 2) === _r + ? ((r = _r), (_e += 2)) + : ((r = mr), 0 === Ze && s(Mr))), + Ze--, + r === mr && 0 === Ze && s(Dr), + r + ); + } + + function g() { + var r; + return ( + Ze++, + Hr.test(t.charAt(_e)) + ? ((r = t.charAt(_e)), _e++) + : ((r = mr), 0 === Ze && s(Ur)), + Ze--, + r === mr && 0 === Ze && s(Nr), + r + ); + } + + function A() { + var r, e, n, u, o, i; + if ( + (Ze++, + (r = _e), + 35 === t.charCodeAt(_e) ? ((e = Ir), _e++) : ((e = mr), 0 === Ze && s(Rr)), + e !== mr) + ) { + for ( + n = [], + u = _e, + o = _e, + Ze++, + i = d(), + Ze--, + i === mr ? (o = void 0) : ((_e = o), (o = mr)), + o !== mr + ? (t.length > _e + ? ((i = t.charAt(_e)), _e++) + : ((i = mr), 0 === Ze && s(qr)), + i !== mr ? (u = o = [o, i]) : ((_e = u), (u = mr))) + : ((_e = u), (u = mr)); + u !== mr; + + ) + n.push(u), + (u = _e), + (o = _e), + Ze++, + (i = d()), + Ze--, + i === mr ? (o = void 0) : ((_e = o), (o = mr)), + o !== mr + ? (t.length > _e + ? ((i = t.charAt(_e)), _e++) + : ((i = mr), 0 === Ze && s(qr)), + i !== mr ? (u = o = [o, i]) : ((_e = u), (u = mr))) + : ((_e = u), (u = mr)); + n !== mr ? (r = e = [e, n]) : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return Ze--, r === mr && ((e = mr), 0 === Ze && s(Zr)), r; + } + + function C() { + var r, e, n, u, o, i; + if (((r = _e), (e = y()) !== mr)) { + for (n = [], u = g(); u !== mr; ) n.push(u), (u = g()); + if (n !== mr) + if ( + (61 === t.charCodeAt(_e) + ? ((u = Qr), _e++) + : ((u = mr), 0 === Ze && s(Yr)), + u !== mr) + ) { + for (o = [], i = g(); i !== mr; ) o.push(i), (i = g()); + o !== mr && (i = T()) !== mr + ? ((Me = r), (r = e = kr(e, i))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + else (_e = r), (r = mr); + } else (_e = r), (r = mr); + return r; + } + + function y() { + var r; + return (r = b()) === mr && (r = x()), r; + } + + function b() { + var r, t, e; + if (((r = _e), (t = []), (e = m()) !== mr)) + for (; e !== mr; ) t.push(e), (e = m()); + else t = mr; + return t !== mr && ((Me = r), (t = zr())), (r = t); + } + + function m() { + var r; + return ( + Ze++, + Jr.test(t.charAt(_e)) + ? ((r = t.charAt(_e)), _e++) + : ((r = mr), 0 === Ze && s(Pr)), + Ze--, + r === mr && 0 === Ze && s(Br), + r + ); + } + + function x() { + var r, t, e; + if (((r = _e), S() !== mr)) { + if (((t = []), (e = j()) !== mr)) for (; e !== mr; ) t.push(e), (e = j()); + else t = mr; + t !== mr && (e = S()) !== mr + ? ((Me = r), (r = Lr(t))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return r; + } + + function S() { + var r; + return ( + Ze++, + 34 === t.charCodeAt(_e) ? ((r = Wr), _e++) : ((r = mr), 0 === Ze && s(Gr)), + Ze--, + r === mr && 0 === Ze && s(Vr), + r + ); + } + + function w() { + var r; + return ( + Ze++, + 39 === t.charCodeAt(_e) ? ((r = Xr), _e++) : ((r = mr), 0 === Ze && s($r)), + Ze--, + r === mr && 0 === Ze && s(Kr), + r + ); + } + + function F() { + var r; + return ( + Ze++, + t.substr(_e, 3) === tt + ? ((r = tt), (_e += 3)) + : ((r = mr), 0 === Ze && s(et)), + Ze--, + r === mr && 0 === Ze && s(rt), + r + ); + } + + function E() { + var r; + return ( + Ze++, + t.substr(_e, 3) === ut + ? ((r = ut), (_e += 3)) + : ((r = mr), 0 === Ze && s(ot)), + Ze--, + r === mr && 0 === Ze && s(nt), + r + ); + } + + function T() { + var r; + return ( + (r = D()) === mr && + (r = L()) === mr && + (r = er()) === mr && + (r = V()) === mr && + (r = K()) === mr && + (r = vr()) === mr && + (r = Ar()), + r + ); + } + + function D() { + var r; + return (r = Q()) === mr && (r = O()) === mr && (r = B()) === mr && (r = R()), r; + } + + function O() { + var r, t, e; + if (((r = _e), S() !== mr)) { + for (t = [], e = j(); e !== mr; ) t.push(e), (e = j()); + t !== mr && (e = S()) !== mr + ? ((Me = r), (r = it(t))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return r; + } + + function j() { + var r; + return (r = _()) === mr && (r = M()), r; + } + + function _() { + var r, e, n; + return ( + Ze++, + (r = _e), + (e = _e), + Ze++, + (n = d()), + Ze--, + n === mr ? (e = void 0) : ((_e = e), (e = mr)), + e !== mr + ? (ct.test(t.charAt(_e)) + ? ((n = t.charAt(_e)), _e++) + : ((n = mr), 0 === Ze && s(ft)), + n !== mr ? ((Me = r), (r = e = zr())) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((e = mr), 0 === Ze && s(at)), + r + ); + } + + function M() { + var r, e, n, u; + return ( + (r = _e), + H() !== mr + ? ((e = N()) === mr && + (e = S()) === mr && + (e = H()) === mr && + ((e = _e), + 117 === t.charCodeAt(_e) + ? ((n = st), _e++) + : ((n = mr), 0 === Ze && s(lt)), + n !== mr && (u = U()) !== mr + ? (e = n = [n, u]) + : ((_e = e), (e = mr)), + e === mr && + ((e = _e), + 85 === t.charCodeAt(_e) + ? ((n = ht), _e++) + : ((n = mr), 0 === Ze && s(pt)), + n !== mr && (u = Z()) !== mr + ? (e = n = [n, u]) + : ((_e = e), (e = mr)))), + e !== mr ? ((Me = r), (r = vt())) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + r + ); + } + + function N() { + var r; + return ( + Ze++, + gt.test(t.charAt(_e)) + ? ((r = t.charAt(_e)), _e++) + : ((r = mr), 0 === Ze && s(At)), + Ze--, + r === mr && 0 === Ze && s(dt), + r + ); + } + + function H() { + var r; + return ( + Ze++, + 92 === t.charCodeAt(_e) ? ((r = yt), _e++) : ((r = mr), 0 === Ze && s(bt)), + Ze--, + r === mr && 0 === Ze && s(Ct), + r + ); + } + + function U() { + var r, t, e, n, u; + return ( + Ze++, + (r = _e), + (t = I()) !== mr && (e = I()) !== mr && (n = I()) !== mr && (u = I()) !== mr + ? (r = t = [t, e, n, u]) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((t = mr), 0 === Ze && s(mt)), + r + ); + } + + function Z() { + var r, t, e, n, u, o, i, a, c; + return ( + Ze++, + (r = _e), + (t = I()) !== mr && + (e = I()) !== mr && + (n = I()) !== mr && + (u = I()) !== mr && + (o = I()) !== mr && + (i = I()) !== mr && + (a = I()) !== mr && + (c = I()) !== mr + ? (r = t = [t, e, n, u, o, i, a, c]) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((t = mr), 0 === Ze && s(xt)), + r + ); + } + + function I() { + var r; + return ( + St.test(t.charAt(_e)) + ? ((r = t.charAt(_e)), _e++) + : ((r = mr), 0 === Ze && s(wt)), + r + ); + } + + function R() { + var r, t, e; + if (((r = _e), w() !== mr)) { + for (t = [], e = q(); e !== mr; ) t.push(e), (e = q()); + t !== mr && (e = w()) !== mr + ? ((Me = r), (r = Ft())) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return r; + } + + function q() { + var r, e, n; + return ( + Ze++, + (r = _e), + (e = _e), + Ze++, + (n = d()), + Ze--, + n === mr ? (e = void 0) : ((_e = e), (e = mr)), + e !== mr + ? (Et.test(t.charAt(_e)) + ? ((n = t.charAt(_e)), _e++) + : ((n = mr), 0 === Ze && s(Tt)), + n !== mr ? (r = e = [e, n]) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((e = mr), 0 === Ze && s(at)), + r + ); + } + + function Q() { + var r, t, e, n; + if (((r = _e), F() !== mr)) + if (((t = d()) === mr && (t = null), t !== mr)) { + for (e = [], n = Y(); n !== mr; ) e.push(n), (n = Y()); + e !== mr && (n = F()) !== mr + ? ((Me = r), (r = Dt(e))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + else (_e = r), (r = mr); + return r; + } + + function Y() { + var r; + return ( + (r = k()) === mr && + ((r = _e), + H() !== mr && d() !== mr + ? ((Me = r), (r = zr())) + : ((_e = r), (r = mr)), + r === mr && (r = d())), + r + ); + } + + function k() { + var r, t, e; + return ( + (r = _e), + (t = _e), + Ze++, + (e = F()), + Ze--, + e === mr ? (t = void 0) : ((_e = t), (t = mr)), + t !== mr && (e = z()) !== mr + ? ((Me = r), (r = t = zr())) + : ((_e = r), (r = mr)), + r === mr && (r = M()), + r + ); + } + + function z() { + var r, e, n; + return ( + Ze++, + (r = _e), + (e = _e), + Ze++, + (n = d()), + Ze--, + n === mr ? (e = void 0) : ((_e = e), (e = mr)), + e !== mr + ? (Ot.test(t.charAt(_e)) + ? ((n = t.charAt(_e)), _e++) + : ((n = mr), 0 === Ze && s(jt)), + n !== mr ? (r = e = [e, n]) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((e = mr), 0 === Ze && s(at)), + r + ); + } + + function B() { + var r, t, e, n; + if (((r = _e), E() !== mr)) + if (((t = d()) === mr && (t = null), t !== mr)) { + for (e = [], n = J(); n !== mr; ) e.push(n), (n = J()); + e !== mr && (n = E()) !== mr + ? ((Me = r), (r = it(e))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + else (_e = r), (r = mr); + return r; + } + + function J() { + var r, e, n; + return ( + (r = _e), + (e = _e), + Ze++, + t.substr(_e, 3) === ut + ? ((n = ut), (_e += 3)) + : ((n = mr), 0 === Ze && s(ot)), + Ze--, + n === mr ? (e = void 0) : ((_e = e), (e = mr)), + e !== mr && (n = P()) !== mr + ? ((Me = r), (r = e = zr())) + : ((_e = r), (r = mr)), + r === mr && (r = d()), + r + ); + } + + function P() { + var r, e, n; + return ( + Ze++, + (r = _e), + (e = _e), + Ze++, + (n = d()), + Ze--, + n === mr ? (e = void 0) : ((_e = e), (e = mr)), + e !== mr + ? (Mt.test(t.charAt(_e)) + ? ((n = t.charAt(_e)), _e++) + : ((n = mr), 0 === Ze && s(Nt)), + n !== mr ? (r = e = [e, n]) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((e = mr), 0 === Ze && s(_t)), + r + ); + } + + function L() { + var r, e; + return ( + (r = _e), + t.substr(_e, 4) === Ht + ? ((e = Ht), (_e += 4)) + : ((e = mr), 0 === Ze && s(Ut)), + e !== mr && ((Me = r), (e = Zt())), + (r = e) === mr && + ((r = _e), + t.substr(_e, 5) === It + ? ((e = It), (_e += 5)) + : ((e = mr), 0 === Ze && s(Rt)), + e !== mr && ((Me = r), (e = qt())), + (r = e)), + r + ); + } + + function V() { + var r, t, e, n; + return ( + (r = _e), + K() !== mr + ? ((t = _e), + (e = W()) !== mr + ? ((n = G()) === mr && (n = null), + n !== mr ? (t = e = [e, n]) : ((_e = t), (t = mr))) + : ((_e = t), (t = mr)), + t === mr && (t = G()), + t !== mr ? ((Me = r), (r = Qt())) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + r + ); + } + + function W() { + var r, e, n, u, o, i, a; + if ( + ((r = _e), + 46 === t.charCodeAt(_e) ? ((e = Yt), _e++) : ((e = mr), 0 === Ze && s(kt)), + e !== mr) + ) + if ((n = tr()) !== mr) { + for ( + u = [], + o = _e, + 95 === t.charCodeAt(_e) + ? ((i = zt), _e++) + : ((i = mr), 0 === Ze && s(Bt)), + i === mr && (i = null), + i !== mr && (a = tr()) !== mr + ? (o = i = [i, a]) + : ((_e = o), (o = mr)); + o !== mr; + + ) + u.push(o), + (o = _e), + 95 === t.charCodeAt(_e) + ? ((i = zt), _e++) + : ((i = mr), 0 === Ze && s(Bt)), + i === mr && (i = null), + i !== mr && (a = tr()) !== mr + ? (o = i = [i, a]) + : ((_e = o), (o = mr)); + u !== mr ? (r = e = [e, n, u]) : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + else (_e = r), (r = mr); + return r; + } + + function G() { + var r, e, n; + return ( + (r = _e), + 101 === t.charCodeAt(_e) ? ((e = Jt), _e++) : ((e = mr), 0 === Ze && s(Pt)), + e === mr && + (69 === t.charCodeAt(_e) + ? ((e = Lt), _e++) + : ((e = mr), 0 === Ze && s(Vt))), + e !== mr && (n = K()) !== mr ? (r = e = [e, n]) : ((_e = r), (r = mr)), + r + ); + } + + function K() { + var r, t; + return ( + (r = _e), + (t = X()) === mr && (t = null), + t !== mr && $() !== mr ? ((Me = r), (r = t = Wt())) : ((_e = r), (r = mr)), + r + ); + } + + function X() { + var r; + return ( + 43 === t.charCodeAt(_e) ? ((r = Gt), _e++) : ((r = mr), 0 === Ze && s(Kt)), + r === mr && + (45 === t.charCodeAt(_e) + ? ((r = Xt), _e++) + : ((r = mr), 0 === Ze && s($t))), + r + ); + } + + function $() { + var r, e, n, u, o, i; + if (((r = _e), (e = rr()) !== mr)) { + if ( + ((n = []), + (u = _e), + 95 === t.charCodeAt(_e) + ? ((o = zt), _e++) + : ((o = mr), 0 === Ze && s(Bt)), + o === mr && (o = null), + o !== mr && (i = tr()) !== mr ? (u = o = [o, i]) : ((_e = u), (u = mr)), + u !== mr) + ) + for (; u !== mr; ) + n.push(u), + (u = _e), + 95 === t.charCodeAt(_e) + ? ((o = zt), _e++) + : ((o = mr), 0 === Ze && s(Bt)), + o === mr && (o = null), + o !== mr && (i = tr()) !== mr + ? (u = o = [o, i]) + : ((_e = u), (u = mr)); + else n = mr; + n !== mr ? (r = e = [e, n]) : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return r === mr && (r = tr()), r; + } + + function rr() { + var r; + return ( + re.test(t.charAt(_e)) + ? ((r = t.charAt(_e)), _e++) + : ((r = mr), 0 === Ze && s(te)), + r + ); + } + + function tr() { + var r; + return ( + ee.test(t.charAt(_e)) + ? ((r = t.charAt(_e)), _e++) + : ((r = mr), 0 === Ze && s(ne)), + r + ); + } + + function er() { + var r, e; + return ( + (r = _e), + nr() !== mr + ? (84 === t.charCodeAt(_e) + ? ((e = ue), _e++) + : ((e = mr), 0 === Ze && s(oe)), + e !== mr && ar() !== mr + ? ((Me = r), (r = ie())) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + r + ); + } + + function nr() { + var r, e, n, u, o, i; + return ( + Ze++, + (r = _e), + (e = ur()) !== mr + ? (45 === t.charCodeAt(_e) + ? ((n = Xt), _e++) + : ((n = mr), 0 === Ze && s($t)), + n !== mr && (u = or()) !== mr + ? (45 === t.charCodeAt(_e) + ? ((o = Xt), _e++) + : ((o = mr), 0 === Ze && s($t)), + o !== mr && (i = ir()) !== mr + ? (r = e = [e, n, u, o, i]) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((e = mr), 0 === Ze && s(ae)), + r + ); + } + + function ur() { + var r, t, e, n, u; + return ( + (r = _e), + (t = tr()) !== mr && + (e = tr()) !== mr && + (n = tr()) !== mr && + (u = tr()) !== mr + ? (r = t = [t, e, n, u]) + : ((_e = r), (r = mr)), + r + ); + } + + function or() { + var r, t, e; + return ( + (r = _e), + (t = tr()) !== mr && (e = tr()) !== mr + ? (r = t = [t, e]) + : ((_e = r), (r = mr)), + r + ); + } + + function ir() { + var r, t, e; + return ( + (r = _e), + (t = tr()) !== mr && (e = tr()) !== mr + ? (r = t = [t, e]) + : ((_e = r), (r = mr)), + r + ); + } + + function ar() { + var r, t, e; + return ( + (r = _e), + (t = cr()) !== mr && (e = pr()) !== mr + ? (r = t = [t, e]) + : ((_e = r), (r = mr)), + r + ); + } + + function cr() { + var r, e, n, u, o, i, a; + return ( + (r = _e), + (e = fr()) !== mr + ? (58 === t.charCodeAt(_e) + ? ((n = ce), _e++) + : ((n = mr), 0 === Ze && s(fe)), + n !== mr && (u = sr()) !== mr + ? (58 === t.charCodeAt(_e) + ? ((o = ce), _e++) + : ((o = mr), 0 === Ze && s(fe)), + o !== mr && (i = lr()) !== mr + ? ((a = hr()) === mr && (a = null), + a !== mr + ? (r = e = [e, n, u, o, i, a]) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + r + ); + } + + function fr() { + var r, t, e; + return ( + Ze++, + (r = _e), + (t = tr()) !== mr && (e = tr()) !== mr + ? (r = t = [t, e]) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((t = mr), 0 === Ze && s(se)), + r + ); + } + + function sr() { + var r, t, e; + return ( + Ze++, + (r = _e), + (t = tr()) !== mr && (e = tr()) !== mr + ? (r = t = [t, e]) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((t = mr), 0 === Ze && s(le)), + r + ); + } + + function lr() { + var r, t, e; + return ( + Ze++, + (r = _e), + (t = tr()) !== mr && (e = tr()) !== mr + ? (r = t = [t, e]) + : ((_e = r), (r = mr)), + Ze--, + r === mr && ((t = mr), 0 === Ze && s(he)), + r + ); + } + + function hr() { + var r, e, n, u; + if ( + ((r = _e), + 46 === t.charCodeAt(_e) ? ((e = Yt), _e++) : ((e = mr), 0 === Ze && s(kt)), + e !== mr) + ) { + if (((n = []), (u = tr()) !== mr)) for (; u !== mr; ) n.push(u), (u = tr()); + else n = mr; + n !== mr ? (r = e = [e, n]) : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return r; + } + + function pr() { + var r, e, n, u, o; + return ( + Ze++, + 90 === t.charCodeAt(_e) ? ((r = ve), _e++) : ((r = mr), 0 === Ze && s(de)), + r === mr && + ((r = _e), + (e = X()) !== mr && (n = fr()) !== mr + ? (58 === t.charCodeAt(_e) + ? ((u = ce), _e++) + : ((u = mr), 0 === Ze && s(fe)), + u !== mr && (o = sr()) !== mr + ? (r = e = [e, n, u, o]) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr))), + Ze--, + r === mr && ((e = mr), 0 === Ze && s(pe)), + r + ); + } + + function vr() { + var r, e, n, u, o, i, a, c, f, l; + if ( + ((r = _e), + 91 === t.charCodeAt(_e) ? ((e = ge), _e++) : ((e = mr), 0 === Ze && s(Ae)), + e !== mr) + ) { + for (n = [], u = gr(); u !== mr; ) n.push(u), (u = gr()); + if (n !== mr) { + if (((u = _e), (o = dr()) !== mr)) { + for (i = [], a = gr(); a !== mr; ) i.push(a), (a = gr()); + if (i !== mr) { + if ( + ((a = _e), + 44 === t.charCodeAt(_e) + ? ((c = Ce), _e++) + : ((c = mr), 0 === Ze && s(ye)), + c !== mr) + ) { + for (f = [], l = gr(); l !== mr; ) f.push(l), (l = gr()); + f !== mr ? (a = c = [c, f]) : ((_e = a), (a = mr)); + } else (_e = a), (a = mr); + a === mr && (a = null), + a !== mr ? (u = o = [o, i, a]) : ((_e = u), (u = mr)); + } else (_e = u), (u = mr); + } else (_e = u), (u = mr); + u === mr && (u = null), + u !== mr + ? (93 === t.charCodeAt(_e) + ? ((o = be), _e++) + : ((o = mr), 0 === Ze && s(me)), + o !== mr ? ((Me = r), (r = e = xe(u))) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + } else (_e = r), (r = mr); + return r; + } + + function dr() { + var r, e, n, u, o, i, a; + if (((r = _e), (e = T()) !== mr)) { + for (n = _e, u = [], o = gr(); o !== mr; ) u.push(o), (o = gr()); + if (u !== mr) + if ( + (44 === t.charCodeAt(_e) + ? ((o = Ce), _e++) + : ((o = mr), 0 === Ze && s(ye)), + o !== mr) + ) { + for (i = [], a = gr(); a !== mr; ) i.push(a), (a = gr()); + i !== mr && (a = dr()) !== mr + ? (n = u = [u, o, i, a]) + : ((_e = n), (n = mr)); + } else (_e = n), (n = mr); + else (_e = n), (n = mr); + n === mr && (n = null), + n !== mr ? ((Me = r), (r = e = Se(e, n))) : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + return r; + } + + function gr() { + var r; + return (r = g()) === mr && (r = d()) === mr && (r = A()), r; + } + + function Ar() { + var r, e, n, u, o, i, a, c, f, l, h; + if ( + ((r = _e), + 123 === t.charCodeAt(_e) ? ((e = we), _e++) : ((e = mr), 0 === Ze && s(Fe)), + e !== mr) + ) { + for (n = [], u = g(); u !== mr; ) n.push(u), (u = g()); + if (n !== mr) { + if (((u = _e), (o = C()) !== mr)) { + for (i = [], a = _e, c = [], f = g(); f !== mr; ) + c.push(f), (f = g()); + if (c !== mr) + if ( + (44 === t.charCodeAt(_e) + ? ((f = Ce), _e++) + : ((f = mr), 0 === Ze && s(ye)), + f !== mr) + ) { + for (l = [], h = g(); h !== mr; ) l.push(h), (h = g()); + l !== mr && (h = C()) !== mr + ? (a = c = [c, f, l, h]) + : ((_e = a), (a = mr)); + } else (_e = a), (a = mr); + else (_e = a), (a = mr); + for (; a !== mr; ) { + for (i.push(a), a = _e, c = [], f = g(); f !== mr; ) + c.push(f), (f = g()); + if (c !== mr) + if ( + (44 === t.charCodeAt(_e) + ? ((f = Ce), _e++) + : ((f = mr), 0 === Ze && s(ye)), + f !== mr) + ) { + for (l = [], h = g(); h !== mr; ) l.push(h), (h = g()); + l !== mr && (h = C()) !== mr + ? (a = c = [c, f, l, h]) + : ((_e = a), (a = mr)); + } else (_e = a), (a = mr); + else (_e = a), (a = mr); + } + if (i !== mr) { + for (a = [], c = g(); c !== mr; ) a.push(c), (c = g()); + a !== mr ? (u = o = [o, i, a]) : ((_e = u), (u = mr)); + } else (_e = u), (u = mr); + } else (_e = u), (u = mr); + u === mr && (u = null), + u !== mr + ? (125 === t.charCodeAt(_e) + ? ((o = Ee), _e++) + : ((o = mr), 0 === Ze && s(Te)), + o !== mr ? ((Me = r), (r = e = De(u))) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + } else (_e = r), (r = mr); + return r; + } + + function Cr() { + var r, e, n, u; + return ( + (r = _e), + 91 === t.charCodeAt(_e) ? ((e = ge), _e++) : ((e = mr), 0 === Ze && s(Ae)), + e !== mr && (n = yr()) !== mr + ? (93 === t.charCodeAt(_e) + ? ((u = be), _e++) + : ((u = mr), 0 === Ze && s(me)), + u !== mr ? ((Me = r), (r = e = Oe(n))) : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)), + r + ); + } + + function yr() { + var r, e, n, u, o, i, a, c, f, l; + if ( + ((r = _e), + 91 === t.charCodeAt(_e) ? ((e = ge), _e++) : ((e = mr), 0 === Ze && s(Ae)), + e !== mr) + ) { + for (n = [], u = g(); u !== mr; ) n.push(u), (u = g()); + if (n !== mr) + if ((u = y()) !== mr) { + for (o = [], i = _e, a = [], c = g(); c !== mr; ) + a.push(c), (c = g()); + if (a !== mr) + if ( + (46 === t.charCodeAt(_e) + ? ((c = Yt), _e++) + : ((c = mr), 0 === Ze && s(kt)), + c !== mr) + ) { + for (f = [], l = g(); l !== mr; ) f.push(l), (l = g()); + f !== mr && (l = y()) !== mr + ? (i = a = [a, c, f, l]) + : ((_e = i), (i = mr)); + } else (_e = i), (i = mr); + else (_e = i), (i = mr); + for (; i !== mr; ) { + for (o.push(i), i = _e, a = [], c = g(); c !== mr; ) + a.push(c), (c = g()); + if (a !== mr) + if ( + (46 === t.charCodeAt(_e) + ? ((c = Yt), _e++) + : ((c = mr), 0 === Ze && s(kt)), + c !== mr) + ) { + for (f = [], l = g(); l !== mr; ) f.push(l), (l = g()); + f !== mr && (l = y()) !== mr + ? (i = a = [a, c, f, l]) + : ((_e = i), (i = mr)); + } else (_e = i), (i = mr); + else (_e = i), (i = mr); + } + if (o !== mr) { + for (i = [], a = g(); a !== mr; ) i.push(a), (a = g()); + i !== mr + ? (93 === t.charCodeAt(_e) + ? ((a = be), _e++) + : ((a = mr), 0 === Ze && s(me)), + a !== mr + ? ((Me = r), (r = e = je(u, o))) + : ((_e = r), (r = mr))) + : ((_e = r), (r = mr)); + } else (_e = r), (r = mr); + } else (_e = r), (r = mr); + else (_e = r), (r = mr); + } else (_e = r), (r = mr); + return r; + } + e = void 0 !== e ? e : {}; + var br, + mr = {}, + xr = { + Expressions: p, + }, + Sr = p, + wr = function () { + return Pe; + }, + Fr = function (r) { + Le = Je(Pe, !0, r); + }, + Er = function (r) { + Le = Je(Pe, !1, r); + }, + Tr = function (r) { + Be(Le.table, r[0]), (Le.table[r[0]] = r[1]); + }, + Dr = a('Newline'), + Or = '\n', + jr = o('\n', !1), + _r = '\r\n', + Mr = o('\r\n', !1), + Nr = a('Whitespace'), + Hr = /^[ \t]/, + Ur = i([' ', '\t'], !1, !1), + Zr = a('Comment'), + Ir = '#', + Rr = o('#', !1), + qr = { + type: 'any', + }, + Qr = '=', + Yr = o('=', !1), + kr = function (r, t) { + return [r, t.value]; + }, + zr = function () { + return n(); + }, + Br = a('[a-z], [A-Z], [0-9], "-", "_"'), + Jr = /^[a-zA-Z0-9\-_]/, + Pr = i([['a', 'z'], ['A', 'Z'], ['0', '9'], '-', '_'], !1, !1), + Lr = function (r) { + return r.join(''); + }, + Vr = a('DoubleQuote'), + Wr = '"', + Gr = o('"', !1), + Kr = a('SingleQuote'), + Xr = "'", + $r = o("'", !1), + rt = a('ThreeDoubleQuotes'), + tt = '"""', + et = o('"""', !1), + nt = a('ThreeSingleQuotes'), + ut = "'''", + ot = o("'''", !1), + it = function (r) { + return { + type: 'String', + value: r.join(''), + }; + }, + at = a('NormalCharacter'), + ct = /^[^\0-\x1F"\\]/, + ft = i([['\0', ''], '"', '\\'], !0, !1), + st = 'u', + lt = o('u', !1), + ht = 'U', + pt = o('U', !1), + vt = function () { + var r = n(); + return r.length <= 2 ? ke(r[1]) : ze(parseInt(r.substr(2), 16)); + }, + dt = a('"b", "f", "n", "r", "t"'), + gt = /^[bfnrt]/, + At = i(['b', 'f', 'n', 'r', 't'], !1, !1), + Ct = a('Backslash'), + yt = '\\', + bt = o('\\', !1), + mt = a('FourHexadecimalDigits'), + xt = a('EightHexadecimalDigits'), + St = /^[0-9A-Fa-f]/, + wt = i( + [ + ['0', '9'], + ['A', 'F'], + ['a', 'f'], + ], + !1, + !1, + ), + Ft = function () { + var r = n(); + return { + type: 'String', + value: r.substr(1, r.length - 2), + }; + }, + Et = /^[^\0-\x08\n-\x1F']/, + Tt = i([['\0', '\b'], ['\n', ''], "'"], !0, !1), + Dt = function (r) { + return { + type: 'String', + value: r.join('').replace(/\\\r?\n(?:\r?\n|[ \t])*/g, ''), + }; + }, + Ot = /^[^\0-\x1F\\]/, + jt = i([['\0', ''], '\\'], !0, !1), + _t = a('AnyCharacter'), + Mt = /^[^\0-\x08\n-\x1F]/, + Nt = i( + [ + ['\0', '\b'], + ['\n', ''], + ], + !0, + !1, + ), + Ht = 'true', + Ut = o('true', !1), + Zt = function () { + return { + type: 'Boolean', + value: !0, + }; + }, + It = 'false', + Rt = o('false', !1), + qt = function () { + return { + type: 'Boolean', + value: !1, + }; + }, + Qt = function () { + var r = n(), + t = parseFloat(r.replace(/_/g, '')); + return ( + Re(t) || u(r + 'is not a 64-bit floating-point number.'), + { + type: 'Float', + value: t, + } + ); + }, + Yt = '.', + kt = o('.', !1), + zt = '_', + Bt = o('_', !1), + Jt = 'e', + Pt = o('e', !1), + Lt = 'E', + Vt = o('E', !1), + Wt = function () { + var r = n(), + t = r.replace(/_/g, ''), + e = !1; + if ('-' === t[0]) { + var o = '-9223372036854775808'; + (t.length > o.length || (t.length === o.length && t > o)) && (e = !0); + } else { + '+' === t[0] && (t = t.substr(1)); + var i = '9223372036854775807'; + (t.length > i.length || (t.length === i.length && t > i)) && (e = !0); + } + return ( + e && u(r + ' is not a 64-bit signed integer.'), + (t = parseInt(t, 10)), + Re(t) || u(r + ' is not a 64-bit signed integer.'), + { + type: 'Integer', + value: t, + } + ); + }, + Gt = '+', + Kt = o('+', !1), + Xt = '-', + $t = o('-', !1), + re = /^[1-9]/, + te = i([['1', '9']], !1, !1), + ee = /^[0-9]/, + ne = i([['0', '9']], !1, !1), + ue = 'T', + oe = o('T', !1), + ie = function () { + var r = n(), + t = new Date(r); + return ( + Re(t.getTime()) || + u( + 'Date-time ' + + r + + ' is invalid. It does not conform to RFC 3339 or this is a browser-specific problem.', + ), + { + type: 'DateTime', + value: t, + } + ); + }, + ae = a('FullDate (YYYY-mm-dd)'), + ce = ':', + fe = o(':', !1), + se = a('Hour (HH)'), + le = a('Minute (MM)'), + he = a('Second (SS)'), + pe = a('TimeOffset (Z or +/-HH:MM)'), + ve = 'Z', + de = o('Z', !1), + ge = '[', + Ae = o('[', !1), + Ce = ',', + ye = o(',', !1), + be = ']', + me = o(']', !1), + xe = function (r) { + for ( + var t = { + type: 'Array', + value: r ? r[0] : [], + }, + e = 0, + n = t.value, + u = n.length; + e < u; + e++ + ) + n[e] = n[e].value; + return t; + }, + Se = function (r, t) { + var e = [r]; + if (t) + for (var n = r.type, o = 0, i = t[3], a = i.length; o < a; o++) + n !== i[o].type && + u(Ye(i[o].value) + ' should be of type "' + n + '".'), + e.push(i[o]); + return e; + }, + we = '{', + Fe = o('{', !1), + Ee = '}', + Te = o('}', !1), + De = function (r) { + var t = {}; + if (r) { + t[r[0][0]] = r[0][1]; + for (var e = 0, n = r[1], u = n.length; e < u; e++) { + var o = n[e][3]; + Be(t, o[0]), (t[o[0]] = o[1]); + } + } + return { + type: 'InlineTable', + value: t, + }; + }, + Oe = function (r) { + return r; + }, + je = function (r, t) { + for (var e = [r], n = 0, u = t.length; n < u; n++) e.push(t[n][3]); + return e; + }, + _e = 0, + Me = 0, + Ne = [ + { + line: 1, + column: 1, + }, + ], + He = 0, + Ue = [], + Ze = 0; + if ('startRule' in e) { + if (!(e.startRule in xr)) + throw new Error('Can\'t start parsing from rule "' + e.startRule + '".'); + Sr = xr[e.startRule]; + } + var Ie, Re, qe, Qe, Ye, ke, ze, Be, Je; + (Ie = function (r) { + return 'Value for ' + r + ' should not be redefined in the same table.'; + }), + (Re = + Number.isFinite || + function (r) { + return 'number' == typeof r && isFinite(r); + }), + (qe = + Array.isArray || + function (r) { + return '[object Array]' === Object.prototype.toString.call(r); + }), + (Qe = function (r, t) { + return Object.prototype.hasOwnProperty.call(r, t); + }), + (Ye = + 'object' == typeof JSON && JSON + ? JSON.stringify + : function (r) { + return ( + '"' + + String(r).replace(/[\x00-\x1F"\\]/g, function (r) { + switch (r) { + case '"': + case '\\': + return '\\' + r; + case '\t': + return '\\t'; + case '\n': + return '\\n'; + case '\r': + return '\\r'; + case '\b': + return '\\b'; + case '\f': + return '\\f'; + default: + var t = r.charCodeAt(0).toString(16); + return '\\u' + '0000'.substr(t.length) + t; + } + }) + + '"' + ); + }), + (ke = function (r) { + switch (r) { + case '"': + case '\\': + return r; + case 't': + return '\t'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 'b': + return '\b'; + case 'f': + return '\f'; + default: + u(Ye(r) + ' cannot be escaped.'); + } + }), + (ze = function (r) { + if ( + ((!Re(r) || r < 0 || r > 1114111) && + u('U+' + r.toString(16) + ' is not a valid Unicode code point.'), + String.fromCodePoint) + ) + return String.fromCodePoint(r); + var t = ''; + return ( + r > 65535 && + ((r -= 65536), + (t += String.fromCharCode(((r >>> 10) & 1023) | 55296)), + (r = 56320 | (1023 & r))), + (t += String.fromCharCode(r)) + ); + }), + (Be = function (r, t) { + Qe(r, t) && u(Ie(Ye(t))); + }), + (Je = function (r, t, e) { + for (var n = '', o = 0, i = e.length; o < i; o++) { + var a = e[o]; + if (((n += (n ? '.' : '') + Ye(a)), Qe(r, a))) + t + ? qe(r[a]) + ? (Ge[n] || u(Ie(n)), + o + 1 === i + ? ((c = {}), r[a].push(c), (r = c)) + : ((n += '.' + Ye(r[a].length - 1)), + (r = r[a][r[a].length - 1]))) + : (Ve[n] || u(Ie(n)), (r = r[a])) + : qe(r[a]) + ? ((Ge[n] && o + 1 !== i) || u(Ie(n)), + (n += '.' + Ye(r[a].length - 1)), + (r = r[a][r[a].length - 1])) + : (Ve[n] || u(Ie(n)), (r = r[a])); + else if (t && o + 1 === i) { + var c = {}; + (r[a] = [c]), (r = c), (Ge[n] = !0); + } else (r = r[a] = {}), (Ve[n] = !0); + } + return ( + t ? Ge[n] || u(Ie(n)) : ((We[n] || Ge[n]) && u(Ie(n)), (We[n] = !0)), + { + table: r, + path: e, + } + ); + }); + var Pe = {}, + Le = { + table: Pe, + path: [], + }, + Ve = {}, + We = {}, + Ge = {}; + if ((br = Sr()) !== mr && _e === t.length) return br; + throw ( + (br !== mr && + _e < t.length && + s({ + type: 'end', + }), + h( + Ue, + He < t.length ? t.charAt(He) : null, + He < t.length ? f(He, He + 1) : f(He, He), + )) + ); + }, + } + ); + })(); + }, + {}, + ], + 2: [ + function (r, t, e) { + + function n(r, t, e, n) { + (this.message = r), (this.offset = t), (this.line = e), (this.column = n); + } + !(function (r, t) { + function e() { + this.constructor = r; + } + (e.prototype = t.prototype), (r.prototype = new e()); + })(n, SyntaxError); + var u = r('./lib/parser'), + o = { + parse: function (r) { + try { + return u.parse(r); + } catch (r) { + throw r instanceof u.SyntaxError + ? ((r.line = r.location.start.line), + (r.column = r.location.start.column), + (r.offset = r.location.start.offset), + new n( + r.message, + r.location.start.offset, + r.location.start.line, + r.location.start.column, + )) + : r; + } + }, + SyntaxError: n, + }; + t.exports = o; + }, + { + './lib/parser': 1, + }, + ], + }, + {}, + [2], + )(2); + }); + + var toml$1 = toml; + + /* Very simple logger interface. + + Each module is expected to create its own logger by doing e.g.: + + const logger = getLogger('my-prefix'); + + and then use it instead of console: + + logger.info('hello', 'world'); + logger.warn('...'); + logger.error('...'); + + The logger automatically adds the prefix "[my-prefix]" to all logs; so e.g., the + above call would print: + + [my-prefix] hello world + + logger.log is intentionally omitted. The idea is that PyScript should not + write anything to console.log, to leave it free for the user. + + Currently, the logger does not to anything more than that. In the future, + we might want to add additional features such as the ability to + enable/disable logs on a global or per-module basis. + */ + const _cache = new Map(); + function getLogger(prefix) { + let logger = _cache.get(prefix); + if (logger === undefined) { + logger = _makeLogger(prefix); + _cache.set(prefix, logger); + } + return logger; + } + function _makeLogger(prefix) { + prefix = '[' + prefix + '] '; + function make(level) { + const out_fn = console[level].bind(console); + function fn(fmt, ...args) { + out_fn(prefix + fmt, ...args); + } + return fn; + } + // 'log' is intentionally omitted + const debug = make('debug'); + const info = make('info'); + const warn = make('warn'); + const error = make('error'); + return { debug, info, warn, error }; + } + + const logger$e = getLogger('pyscript/runtime'); + // VERSION + // Version number of release + const version = '2022.12.1.dev'; + /* + Runtime class is a super class that all different runtimes must respect + and adhere to. + + Currently, the only runtime available is Pyodide as indicated by the + `RuntimeInterpreter` type above. This serves as a Union of types of + different runtimes/interpreters which will be added in near future. + + The class has abstract methods available which each runtime is supposed + to implement. + + Methods available handle loading of the interpreter, initialization, + running code, loading and installation of packages, loading from files etc. + + For an example implementation, refer to the `PyodideRuntime` class + in `pyodide.ts` + */ + class Runtime extends Object { + constructor(config) { + super(); + this.config = config; + } + /** + * Same as run, but Python exceptions are not propagated: instead, they + * are logged to the console. + * + * This is a bad API and should be killed/refactored/changed eventually, + * but for now we have code which relies on it. + * */ + runButDontRaise(code) { + let result; + try { + result = this.run(code); + } + catch (error) { + logger$e.error('Error:', error); + } + return result; + } + } + + const CLOSEBUTTON = ``; + /* + These error codes are used to identify the type of error that occurred. + The convention is: + * PY0 - errors that occur when fetching + * PY1 - errors that occur in config + * PY9 - Deprecation errors + */ + var ErrorCode; + (function (ErrorCode) { + ErrorCode["GENERIC"] = "PY0000"; + ErrorCode["FETCH_ERROR"] = "PY0001"; + ErrorCode["FETCH_NAME_ERROR"] = "PY0002"; + // Currently these are created depending on error code received from fetching + ErrorCode["FETCH_UNAUTHORIZED_ERROR"] = "PY0401"; + ErrorCode["FETCH_FORBIDDEN_ERROR"] = "PY0403"; + ErrorCode["FETCH_NOT_FOUND_ERROR"] = "PY0404"; + ErrorCode["FETCH_SERVER_ERROR"] = "PY0500"; + ErrorCode["FETCH_UNAVAILABLE_ERROR"] = "PY0503"; + ErrorCode["BAD_CONFIG"] = "PY1000"; + ErrorCode["MICROPIP_INSTALL_ERROR"] = "PY1001"; + ErrorCode["TOP_LEVEL_AWAIT"] = "PY9000"; + })(ErrorCode || (ErrorCode = {})); + class UserError extends Error { + constructor(errorCode, message, t = "text") { + super(message); + this.errorCode = errorCode; + this.name = "UserError"; + this.messageType = t; + this.message = `(${errorCode}): ${message}`; + } + } + class FetchError extends Error { + constructor(errorCode, message) { + super(message); + this.name = "FetchError"; + this.errorCode = errorCode; + this.message = `(${errorCode}): ${message}`; + } + } + class InstallError extends UserError { + constructor(errorCode, message) { + super(errorCode, message); + this.name = "InstallError"; + } + } + function _createAlertBanner(message, level = 'error', messageType = 'text', logMessage = true) { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + switch (`log-${level}-${logMessage}`) { + case 'log-error-true': + console.error(message); + break; + case 'log-warning-true': + console.warn(message); + break; + } + const banner = document.createElement('div'); + banner.className = `alert-banner py-${level}`; + if (messageType === 'html') { + banner.innerHTML = message; + } + else { + banner.textContent = message; + } + if (level === 'warning') { + const closeButton = document.createElement('button'); + closeButton.id = 'alert-close-button'; + closeButton.addEventListener('click', () => { + banner.remove(); + }); + closeButton.innerHTML = CLOSEBUTTON; + banner.appendChild(closeButton); + } + document.body.prepend(banner); + } + + function addClasses(element, classes) { + for (const entry of classes) { + element.classList.add(entry); + } + } + function escape(str) { + return str.replace(//g, '>'); + } + function htmlDecode(input) { + const doc = new DOMParser().parseFromString(ltrim(escape(input)), 'text/html'); + return doc.documentElement.textContent; + } + function ltrim(code) { + const lines = code.split('\n'); + if (lines.length == 0) + return code; + const lengths = lines + .filter(line => line.trim().length != 0) + .map(line => { + return line.match(/^\s*/)?.pop()?.length; + }); + const k = Math.min(...lengths); + return k != 0 ? lines.map(line => line.substring(k)).join('\n') : code; + } + let _uniqueIdCounter = 0; + function ensureUniqueId(el) { + if (el.id === '') + el.id = `py-internal-${_uniqueIdCounter++}`; + } + function showWarning(msg, messageType = 'text') { + _createAlertBanner(msg, 'warning', messageType); + } + function handleFetchError(e, singleFile) { + // XXX: inspecting the error message to understand what happened is very + // fragile. We need a better solution. + let errorContent; + if (e.message.includes('Failed to fetch')) { + errorContent = `PyScript: Access to local files + (using "Paths:" in <py-config>) + is not available when directly opening a HTML file; + you must use a webserver to serve the additional files. + See this reference + on starting a simple webserver with Python.`; + } + else if (e.message.includes('404')) { + errorContent = + `PyScript: Loading from file ` + + singleFile + + ` failed with error 404 (File not Found). Are your filename and path are correct?`; + } + else { + errorContent = `PyScript encountered an error while loading from file: ${e.message}`; + } + throw new UserError(ErrorCode.FETCH_ERROR, errorContent, 'html'); + } + function readTextFromPath(path) { + const request = new XMLHttpRequest(); + request.open('GET', path, false); + request.send(); + const returnValue = request.responseText; + return returnValue; + } + function globalExport(name, obj) { + // attach the given object to the global object, so that it is globally + // visible everywhere. Should be used very sparingly! + globalThis[name] = obj; + } + function getAttribute(el, attr) { + if (el.hasAttribute(attr)) { + const value = el.getAttribute(attr); + if (value) { + return value; + } + } + return null; + } + function joinPaths(parts, separator = '/') { + const res = parts + .map(function (part) { + return part.trim().replace(/(^[/]*|[/]*$)/g, ''); + }) + .filter(p => p !== '') + .join(separator || '/'); + if (parts[0].startsWith('/')) { + return '/' + res; + } + return res; + } + function createDeprecationWarning(msg, elementName) { + const banners = document.getElementsByClassName('alert-banner py-warning'); + let bannerCount = 0; + for (const banner of banners) { + if (banner.innerHTML.includes(elementName)) { + bannerCount++; + } + } + if (bannerCount == 0) { + _createAlertBanner(msg, 'warning'); + } + } + + const logger$d = getLogger('py-config'); + const allKeys = { + string: ['name', 'description', 'version', 'type', 'author_name', 'author_email', 'license'], + number: ['schema_version'], + array: ['runtimes', 'packages', 'fetch', 'plugins'], + }; + const defaultConfig$1 = { + schema_version: 1, + type: 'app', + runtimes: [ + { + src: 'https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js', + name: 'pyodide-0.21.3', + lang: 'python', + }, + ], + packages: [], + fetch: [], + plugins: [], + }; + function loadConfigFromElement(el) { + let srcConfig; + let inlineConfig; + if (el === null) { + srcConfig = {}; + inlineConfig = {}; + } + else { + const configType = getAttribute(el, 'type') || 'toml'; + srcConfig = extractFromSrc(el, configType); + inlineConfig = extractFromInline(el, configType); + } + srcConfig = mergeConfig(srcConfig, defaultConfig$1); + const result = mergeConfig(inlineConfig, srcConfig); + result.pyscript = { + version: version, + time: new Date().toISOString(), + }; + return result; + } + function extractFromSrc(el, configType) { + const src = getAttribute(el, 'src'); + if (src) { + logger$d.info('loading ', src); + return validateConfig(readTextFromPath(src), configType); + } + return {}; + } + function extractFromInline(el, configType) { + if (el.innerHTML !== '') { + logger$d.info('loading content'); + return validateConfig(htmlDecode(el.innerHTML), configType); + } + return {}; + } + function fillUserData(inputConfig, resultConfig) { + for (const key in inputConfig) { + // fill in all extra keys ignored by the validator + if (!(key in defaultConfig$1)) { + resultConfig[key] = inputConfig[key]; + } + } + return resultConfig; + } + function mergeConfig(inlineConfig, externalConfig) { + if (Object.keys(inlineConfig).length === 0 && Object.keys(externalConfig).length === 0) { + return defaultConfig$1; + } + else if (Object.keys(inlineConfig).length === 0) { + return externalConfig; + } + else if (Object.keys(externalConfig).length === 0) { + return inlineConfig; + } + else { + let merged = {}; + for (const keyType in allKeys) { + const keys = allKeys[keyType]; + keys.forEach(function (item) { + if (keyType === 'boolean') { + merged[item] = + typeof inlineConfig[item] !== 'undefined' ? inlineConfig[item] : externalConfig[item]; + } + else { + merged[item] = inlineConfig[item] || externalConfig[item]; + } + }); + } + // fill extra keys from external first + // they will be overridden by inline if extra keys also clash + merged = fillUserData(externalConfig, merged); + merged = fillUserData(inlineConfig, merged); + return merged; + } + } + function parseConfig(configText, configType = 'toml') { + let config; + if (configType === 'toml') { + try { + // TOML parser is soft and can parse even JSON strings, this additional check prevents it. + if (configText.trim()[0] === '{') { + throw new UserError(ErrorCode.BAD_CONFIG, `The config supplied: ${configText} is an invalid TOML and cannot be parsed`); + } + config = toml$1.parse(configText); + } + catch (err) { + const errMessage = err.toString(); + throw new UserError(ErrorCode.BAD_CONFIG, `The config supplied: ${configText} is an invalid TOML and cannot be parsed: ${errMessage}`); + } + } + else if (configType === 'json') { + try { + config = JSON.parse(configText); + } + catch (err) { + const errMessage = err.toString(); + throw new UserError(ErrorCode.BAD_CONFIG, `The config supplied: ${configText} is an invalid JSON and cannot be parsed: ${errMessage}`); + } + } + else { + throw new UserError(ErrorCode.BAD_CONFIG, `The type of config supplied '${configType}' is not supported, supported values are ["toml", "json"]`); + } + return config; + } + function validateConfig(configText, configType = 'toml') { + const config = parseConfig(configText, configType); + const finalConfig = {}; + for (const keyType in allKeys) { + const keys = allKeys[keyType]; + keys.forEach(function (item) { + if (validateParamInConfig(item, keyType, config)) { + if (item === 'runtimes') { + finalConfig[item] = []; + const runtimes = config[item]; + runtimes.forEach(function (eachRuntime) { + const runtimeConfig = {}; + for (const eachRuntimeParam in eachRuntime) { + if (validateParamInConfig(eachRuntimeParam, 'string', eachRuntime)) { + runtimeConfig[eachRuntimeParam] = eachRuntime[eachRuntimeParam]; + } + } + finalConfig[item].push(runtimeConfig); + }); + } + else if (item === 'fetch') { + finalConfig[item] = []; + const fetchList = config[item]; + fetchList.forEach(function (eachFetch) { + const eachFetchConfig = {}; + for (const eachFetchConfigParam in eachFetch) { + const targetType = eachFetchConfigParam === 'files' ? 'array' : 'string'; + if (validateParamInConfig(eachFetchConfigParam, targetType, eachFetch)) { + eachFetchConfig[eachFetchConfigParam] = eachFetch[eachFetchConfigParam]; + } + } + finalConfig[item].push(eachFetchConfig); + }); + } + else { + finalConfig[item] = config[item]; + } + } + }); + } + return fillUserData(config, finalConfig); + } + function validateParamInConfig(paramName, paramType, config) { + if (paramName in config) { + return paramType === 'array' ? Array.isArray(config[paramName]) : typeof config[paramName] === paramType; + } + return false; + } + + const logger$c = getLogger('plugin'); + class Plugin { + /** Validate the configuration of the plugin and handle default values. + * + * Individual plugins are expected to check that the config keys/sections + * which are relevant to them contains valid values, and to raise an error + * if they contains unknown keys. + * + * This is also a good place where set default values for those keys which + * are not specified by the user. + * + * This hook should **NOT** contain expensive operations, else it delays + * the download of the python interpreter which is initiated later. + */ + configure(config) { } + /** The preliminary initialization phase is complete and we are about to + * download and launch the Python interpreter. + * + * We can assume that the page is already shown to the user and that the + * DOM content has been loaded. This is a good place where to add tags to + * the DOM, if needed. + * + * This hook should **NOT** contain expensive operations, else it delays + * the download of the python interpreter which is initiated later. + */ + beforeLaunch(config) { } + /** The Python interpreter has been launched, the virtualenv has been + * installed and we are ready to execute user code. + * + * The tags will be executed after this hook. + */ + afterSetup(runtime) { } + /** Startup complete. The interpreter is initialized and ready, user + * scripts have been executed: the main initialization logic ends here and + * the page is ready to accept user interactions. + */ + afterStartup(runtime) { } + /** Called when an UserError is raised + */ + onUserError(error) { } + } + class PluginManager { + constructor() { + this._plugins = []; + this._pythonPlugins = []; + } + add(...plugins) { + for (const p of plugins) + this._plugins.push(p); + } + addPythonPlugin(plugin) { + this._pythonPlugins.push(plugin); + } + configure(config) { + for (const p of this._plugins) + p.configure(config); + for (const p of this._pythonPlugins) + p.configure?.(config); + } + beforeLaunch(config) { + for (const p of this._plugins) + p.beforeLaunch(config); + } + afterSetup(runtime) { + for (const p of this._plugins) + p.afterSetup(runtime); + for (const p of this._pythonPlugins) + p.afterSetup?.(runtime); + } + afterStartup(runtime) { + for (const p of this._plugins) + p.afterStartup(runtime); + for (const p of this._pythonPlugins) + p.afterStartup?.(runtime); + } + onUserError(error) { + for (const p of this._plugins) + p.onUserError(error); + for (const p of this._pythonPlugins) + p.onUserError?.(error); + } + } + /** + * Defines a new CustomElement (via customElement.defines) with `tag`, + * where the new CustomElement is a proxy that delegates the logic to + * pyPluginClass. + * + * @param tag - tag that will be used to define the new CustomElement (i.e: "py-script") + * @param pyPluginClass - class that will be used to create instance to be + * used as CustomElement logic handler. Any DOM event + * received by the newly created CustomElement will be + * delegated to that instance. + */ + function define_custom_element(tag, pyPluginClass) { + logger$c.info(`creating plugin: ${tag}`); + class ProxyCustomElement extends HTMLElement { + constructor() { + logger$c.debug(`creating ${tag} plugin instance`); + super(); + this.shadow = this.attachShadow({ mode: 'open' }); + this.wrapper = document.createElement('slot'); + this.shadow.appendChild(this.wrapper); + this.originalInnerHTML = this.innerHTML; + this.pyPluginInstance = pyPluginClass(this); + } + connectedCallback() { + const innerHTML = this.pyPluginInstance.connect(); + if (typeof innerHTML === 'string') + this.innerHTML = innerHTML; + } + } + customElements.define(tag, ProxyCustomElement); + } + + const logger$b = getLogger('pyexec'); + function pyExec(runtime, pysrc, outElem) { + //This is pyscript.py + const pyscript_py = runtime.interpreter.pyimport('pyscript'); + ensureUniqueId(outElem); + pyscript_py.set_current_display_target(outElem.id); + try { + try { + if (pyscript_py.uses_top_level_await(pysrc)) { + throw new UserError(ErrorCode.TOP_LEVEL_AWAIT, 'The use of top-level "await", "async for", and ' + + '"async with" is deprecated.' + + '\nPlease write a coroutine containing ' + + 'your code and schedule it using asyncio.ensure_future() or similar.' + + '\nSee https://docs.pyscript.net/latest/guides/asyncio.html for more information.'); + } + return runtime.run(pysrc); + } + catch (err) { + // XXX: currently we display exceptions in the same position as + // the output. But we probably need a better way to do that, + // e.g. allowing plugins to intercept exceptions and display them + // in a configurable way. + displayPyException(err, outElem); + } + } + finally { + pyscript_py.set_current_display_target(undefined); + pyscript_py.destroy(); + } + } + /** + * Javascript API to call the python display() function + * + * Expected usage: + * pyDisplay(runtime, obj); + * pyDisplay(runtime, obj, { target: targetID }); + */ + function pyDisplay(runtime, obj, kwargs) { + const display = runtime.globals.get('display'); + if (kwargs === undefined) + display(obj); + else { + display.callKwargs(obj, kwargs); + } + } + function displayPyException(err, errElem) { + //addClasses(errElem, ['py-error']) + const pre = document.createElement('pre'); + pre.className = 'py-error'; + if (err.name === 'PythonError') { + // err.message contains the python-level traceback (i.e. a string + // starting with: "Traceback (most recent call last) ..." + logger$b.error('Python exception:\n' + err.message); + pre.innerText = err.message; + } + else { + // this is very likely a normal JS exception. The best we can do is to + // display it as is. + logger$b.error('Non-python exception:\n' + err); + pre.innerText = err; + } + errElem.appendChild(pre); + } + + /* + This is a fetch wrapper that handles any non 200 response and throws a FetchError + with the right ErrorCode. + TODO: Should we only throw on 4xx and 5xx responses? + */ + async function robustFetch(url, options) { + const response = await fetch(url, options); + // Note that response.ok is true for 200-299 responses + if (!response.ok) { + const errorMsg = `Fetching from URL ${url} failed with error ${response.status} (${response.statusText}).`; + switch (response.status) { + case 404: + throw new FetchError(ErrorCode.FETCH_NOT_FOUND_ERROR, errorMsg); + case 401: + throw new FetchError(ErrorCode.FETCH_UNAUTHORIZED_ERROR, errorMsg); + case 403: + throw new FetchError(ErrorCode.FETCH_FORBIDDEN_ERROR, errorMsg); + case 500: + throw new FetchError(ErrorCode.FETCH_SERVER_ERROR, errorMsg); + case 503: + throw new FetchError(ErrorCode.FETCH_UNAVAILABLE_ERROR, errorMsg); + default: + throw new FetchError(ErrorCode.FETCH_ERROR, errorMsg); + } + } + return response; + } + + const logger$a = getLogger('py-script'); + function make_PyScript(runtime) { + class PyScript extends HTMLElement { + async connectedCallback() { + if (this.hasAttribute('output')) { + const deprecationMessage = ("The 'output' attribute is deprecated and ignored. You should use " + + "'display()' to output the content to a specific element. " + + 'For example display(myElement, target="divID").'); + showWarning(deprecationMessage); + } + ensureUniqueId(this); + // Save innerHTML information in srcCode so we can access it later + // once we clean innerHTML (which is required since we don't want + // source code to be rendered on the screen) + this.srcCode = this.innerHTML; + const pySrc = await this.getPySrc(); + this.innerHTML = ''; + pyExec(runtime, pySrc, this); + } + async getPySrc() { + if (this.hasAttribute('src')) { + const url = this.getAttribute('src'); + try { + const response = await robustFetch(url); + return await response.text(); + } + catch (e) { + _createAlertBanner(e.message); + this.innerHTML = ''; + throw e; + } + } + else { + return htmlDecode(this.srcCode); + } + } + } + return PyScript; + } + /** Defines all possible py-on* and their corresponding event types */ + const pyAttributeToEvent = new Map([ + // Leaving pys-onClick and pys-onKeyDown for backward compatibility + ['pys-onClick', 'click'], + ['pys-onKeyDown', 'keydown'], + ['py-onClick', 'click'], + ['py-onKeyDown', 'keydown'], + // Window Events + ['py-afterprint', 'afterprint'], + ['py-beforeprint', 'beforeprint'], + ['py-beforeunload', 'beforeunload'], + ['py-error', 'error'], + ['py-hashchange', 'hashchange'], + ['py-load', 'load'], + ['py-message', 'message'], + ['py-offline', 'offline'], + ['py-online', 'online'], + ['py-pagehide', 'pagehide'], + ['py-pageshow', 'pageshow'], + ['py-popstate', 'popstate'], + ['py-resize', 'resize'], + ['py-storage', 'storage'], + ['py-unload', 'unload'], + // Form Events + ['py-blur', 'blur'], + ['py-change', 'change'], + ['py-contextmenu', 'contextmenu'], + ['py-focus', 'focus'], + ['py-input', 'input'], + ['py-invalid', 'invalid'], + ['py-reset', 'reset'], + ['py-search', 'search'], + ['py-select', 'select'], + ['py-submit', 'submit'], + // Keyboard Events + ['py-keydown', 'keydown'], + ['py-keypress', 'keypress'], + ['py-keyup', 'keyup'], + // Mouse Events + ['py-click', 'click'], + ['py-dblclick', 'dblclick'], + ['py-mousedown', 'mousedown'], + ['py-mousemove', 'mousemove'], + ['py-mouseout', 'mouseout'], + ['py-mouseover', 'mouseover'], + ['py-mouseup', 'mouseup'], + ['py-mousewheel', 'mousewheel'], + ['py-wheel', 'wheel'], + // Drag Events + ['py-drag', 'drag'], + ['py-dragend', 'dragend'], + ['py-dragenter', 'dragenter'], + ['py-dragleave', 'dragleave'], + ['py-dragover', 'dragover'], + ['py-dragstart', 'dragstart'], + ['py-drop', 'drop'], + ['py-scroll', 'scroll'], + // Clipboard Events + ['py-copy', 'copy'], + ['py-cut', 'cut'], + ['py-paste', 'paste'], + // Media Events + ['py-abort', 'abort'], + ['py-canplay', 'canplay'], + ['py-canplaythrough', 'canplaythrough'], + ['py-cuechange', 'cuechange'], + ['py-durationchange', 'durationchange'], + ['py-emptied', 'emptied'], + ['py-ended', 'ended'], + ['py-loadeddata', 'loadeddata'], + ['py-loadedmetadata', 'loadedmetadata'], + ['py-loadstart', 'loadstart'], + ['py-pause', 'pause'], + ['py-play', 'play'], + ['py-playing', 'playing'], + ['py-progress', 'progress'], + ['py-ratechange', 'ratechange'], + ['py-seeked', 'seeked'], + ['py-seeking', 'seeking'], + ['py-stalled', 'stalled'], + ['py-suspend', 'suspend'], + ['py-timeupdate', 'timeupdate'], + ['py-volumechange', 'volumechange'], + ['py-waiting', 'waiting'], + // Misc Events + ['py-toggle', 'toggle'], + ]); + /** Initialize all elements with py-* handlers attributes */ + function initHandlers(runtime) { + logger$a.debug('Initializing py-* event handlers...'); + for (const pyAttribute of pyAttributeToEvent.keys()) { + createElementsWithEventListeners(runtime, pyAttribute); + } + } + /** Initializes an element with the given py-on* attribute and its handler */ + function createElementsWithEventListeners(runtime, pyAttribute) { + const matches = document.querySelectorAll(`[${pyAttribute}]`); + for (const el of matches) { + if (el.id.length === 0) { + throw new TypeError(`<${el.tagName.toLowerCase()}> must have an id attribute, when using the ${pyAttribute} attribute`); + } + const handlerCode = el.getAttribute(pyAttribute); + const event = pyAttributeToEvent.get(pyAttribute); + if (pyAttribute === 'pys-onClick' || pyAttribute === 'pys-onKeyDown') { + console.warn('Use of pys-onClick and pys-onKeyDown attributes is deprecated in favor of py-onClick() and py-onKeyDown(). pys-on* attributes will be deprecated in a future version of PyScript.'); + const source = ` + from pyodide.ffi import create_proxy + Element("${el.id}").element.addEventListener("${event}", create_proxy(${handlerCode})) + `; + runtime.run(source); + } + else { + el.addEventListener(event, () => { + runtime.run(handlerCode); + }); + } + // TODO: Should we actually map handlers in JS instead of Python? + // el.onclick = (evt: any) => { + // console.log("click"); + // new Promise((resolve, reject) => { + // setTimeout(() => { + // console.log('Inside') + // }, 300); + // }).then(() => { + // console.log("resolved") + // }); + // // let handlerCode = el.getAttribute('py-onClick'); + // // pyodide.runPython(handlerCode); + // } + } + } + /** Mount all elements with attribute py-mount into the Python namespace */ + function mountElements(runtime) { + const matches = document.querySelectorAll('[py-mount]'); + logger$a.info(`py-mount: found ${matches.length} elements`); + let source = ''; + for (const el of matches) { + const mountName = el.getAttribute('py-mount') || el.id.split('-').join('_'); + source += `\n${mountName} = Element("${el.id}")`; + } + runtime.run(source); + } + + const logger$9 = getLogger('pyscript/pyodide'); + class PyodideRuntime extends Runtime { + constructor(config, stdio, src = 'https://cdn.jsdelivr.net/pyodide/v0.21.3/full/pyodide.js', name = 'pyodide-default', lang = 'python') { + logger$9.info('Runtime config:', { name, lang, src }); + super(config); + this.stdio = stdio; + this.src = src; + this.name = name; + this.lang = lang; + } + /** + * Although `loadPyodide` is used below, + * notice that it is not imported i.e. + * import { loadPyodide } from 'pyodide'; + * is not used at the top of this file. + * + * This is because, if it's used, loadPyodide + * behaves mischievously i.e. it tries to load + * `pyodide.asm.js` and `pyodide_py.tar` but + * with paths that are wrong such as: + * + * http://127.0.0.1:8080/build/pyodide_py.tar + * which results in a 404 since `build` doesn't + * contain these files and is clearly the wrong + * path. + */ + async loadInterpreter() { + logger$9.info('Loading pyodide'); + this.interpreter = await loadPyodide({ + stdout: (msg) => { + this.stdio.stdout_writeline(msg); + }, + stderr: (msg) => { + this.stdio.stderr_writeline(msg); + }, + fullStdLib: false, + }); + this.globals = this.interpreter.globals; + if (this.config.packages) { + logger$9.info("Found packages in configuration to install. Loading micropip..."); + await this.loadPackage('micropip'); + } + logger$9.info('pyodide loaded and initialized'); + } + run(code) { + return this.interpreter.runPython(code); + } + registerJsModule(name, module) { + this.interpreter.registerJsModule(name, module); + } + async loadPackage(names) { + logger$9.info(`pyodide.loadPackage: ${names.toString()}`); + await this.interpreter.loadPackage(names, logger$9.info.bind(logger$9), logger$9.info.bind(logger$9)); + } + async installPackage(package_name) { + if (package_name.length > 0) { + logger$9.info(`micropip install ${package_name.toString()}`); + const micropip = this.interpreter.pyimport('micropip'); + try { + await micropip.install(package_name); + micropip.destroy(); + } + catch (e) { + let exceptionMessage = `Unable to install package(s) '` + package_name + `'.`; + // If we can't fetch `package_name` micropip.install throws a huge + // Python traceback in `e.message` this logic is to handle the + // error and throw a more sensible error message instead of the + // huge traceback. + if (e.message.includes("Can't find a pure Python 3 wheel")) { + exceptionMessage += (` Reason: Can't find a pure Python 3 Wheel for package(s) '` + package_name + + `'. See: https://pyodide.org/en/stable/usage/faq.html#micropip-can-t-find-a-pure-python-wheel ` + + `for more information.`); + } + else if (e.message.includes("Can't fetch metadata")) { + exceptionMessage += (" Unable to find package in PyPI. " + + "Please make sure you have entered a correct package name."); + } + else { + exceptionMessage += (` Reason: ${e.message}. Please open an issue at ` + + `https://github.com/pyscript/pyscript/issues/new if you require help or ` + + `you think it's a bug.`); + } + logger$9.error(e); + throw new InstallError(ErrorCode.MICROPIP_INSTALL_ERROR, exceptionMessage); + } + } + } + /** + * + * @param path : the path in the filesystem + * @param fetch_path : the path to be fetched + * + * Given a file available at `fetch_path` URL (eg: `http://dummy.com/hi.py`), + * the function downloads the file and saves it to the `path` (eg: `a/b/c/foo.py`) + * on the FS. + * + * Example usage: + * await loadFromFile(`a/b/c/foo.py`, `http://dummy.com/hi.py`) + * + * Nested paths are iteratively analysed and each part is created + * if it doesn't exist. + * + * The analysis returns if the part exists and if it's parent directory exists + * Due to the manner in which we proceed, the parent will ALWAYS exist. + * + * The iteration proceeds in the following manner for `a/b/c/foo.py`: + * + * - `a` doesn't exist but it's parent i.e. `root` exists --> create `a` + * - `a/b` doesn't exist but it's parent i.e. `a` exists --> create `a/b` + * - `a/b/c` doesn't exist but it's parent i.e. `a/b` exists --> create `a/b/c` + * + * Finally, write content of `http://dummy.com/hi.py` to `a/b/c/foo.py` + * + * NOTE: The `path` parameter expects to have the `filename` in it i.e. + * `a/b/c/foo.py` is valid while `a/b/c` (i.e. only the folders) are incorrect. + */ + async loadFromFile(path, fetch_path) { + const pathArr = path.split('/'); + const filename = pathArr.pop(); + for (let i = 0; i < pathArr.length; i++) { + // iteratively calculates parts of the path i.e. `a`, `a/b`, `a/b/c` for `a/b/c/foo.py` + const eachPath = pathArr.slice(0, i + 1).join('/'); + // analyses `eachPath` and returns if it exists along with if its parent directory exists or not + const { exists, parentExists } = this.interpreter.FS.analyzePath(eachPath); + // due to the iterative manner in which we proceed, the parent directory should ALWAYS exist + if (!parentExists) { + throw new Error(`'INTERNAL ERROR! cannot create ${path}, this should never happen'`); + } + // creates `eachPath` if it doesn't exist + if (!exists) { + this.interpreter.FS.mkdir(eachPath); + } + } + // `robustFetch` checks for failures in getting a response + const response = await robustFetch(fetch_path); + const buffer = await response.arrayBuffer(); + const data = new Uint8Array(buffer); + pathArr.push(filename); + // opens a file descriptor for the file at `path` + const stream = this.interpreter.FS.open(pathArr.join('/'), 'w'); + this.interpreter.FS.write(stream, data, 0, data.length, 0); + this.interpreter.FS.close(stream); + } + invalidate_module_path_cache() { + const importlib = this.interpreter.pyimport("importlib"); + importlib.invalidate_caches(); + } + } + + function calculatePaths(fetch_cfg) { + const fetchPaths = []; + const paths = []; + fetch_cfg.forEach(function (each_fetch_cfg) { + const from = each_fetch_cfg.from || ''; + const to_folder = each_fetch_cfg.to_folder || '.'; + const to_file = each_fetch_cfg.to_file; + const files = each_fetch_cfg.files; + if (files !== undefined) { + if (to_file !== undefined) { + throw new UserError(ErrorCode.BAD_CONFIG, `Cannot use 'to_file' and 'files' parameters together!`); + } + for (const each_f of files) { + const each_fetch_path = joinPaths([from, each_f]); + fetchPaths.push(each_fetch_path); + const each_path = joinPaths([to_folder, each_f]); + paths.push(each_path); + } + } + else { + fetchPaths.push(from); + const filename = to_file || from.split('/').pop(); + if (filename === '') { + throw new UserError(ErrorCode.BAD_CONFIG, `Couldn't determine the filename from the path ${from}, please supply 'to_file' parameter.`); + } + else { + paths.push(joinPaths([to_folder, filename])); + } + } + }); + return [paths, fetchPaths]; + } + + /** + The data structure for documents. @nonabstract + */ + 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 /* Open.To */); + if (text.length) + text.decompose(0, text.length, parts, 1 /* Open.From */ | 2 /* Open.To */); + this.decompose(to, this.length, parts, 1 /* Open.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 start = this.scanIdentical(other, 1), end = this.length - this.scanIdentical(other, -1); + let a = new RawTextCursor(this), b = new RawTextCursor(other); + for (let skip = start, pos = start;;) { + a.next(skip); + b.next(skip); + skip = 0; + if (a.lineBreak != b.lineBreak || a.done != b.done || a.value != b.value) + return false; + pos += a.value.length; + if (a.done || pos >= end) + 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. + */ + 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); } + /** + Return a cursor that iterates over the given range of lines, + _without_ returning the line breaks between, and yielding empty + strings for empty lines. + + When `from` and `to` are given, they should be 1-based line numbers. + */ + iterLines(from, to) { + let inner; + if (from == null) { + inner = this.iter(); + } + else { + if (to == null) + to = this.lines + 1; + let start = this.line(from).from; + inner = this.iterRange(start, Math.max(start, to == this.lines + 1 ? this.length : to <= 1 ? 0 : this.line(to - 1).to)); + } + return new LineCursor(inner); + } + /** + @internal + */ + toString() { return this.sliceString(0); } + /** + Convert the document to an array of lines (which can be + deserialized again via [`Text.of`](https://codemirror.net/6/docs/ref/#state.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 /* Tree.Branch */ ? new TextLeaf(text) : TextNode.from(TextLeaf.split(text, [])); + } + } + // 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 /* Open.From */) { + let prev = target.pop(); + let joined = appendText(text.text, prev.text.slice(), 0, text.length); + if (joined.length <= 32 /* Tree.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 /* Tree.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); + } + scanIdentical() { return 0; } + static split(text, target) { + let part = [], len = -1; + for (let line of text) { + part.push(line); + len += line.length + 1; + if (part.length == 32 /* Tree.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 /* Open.From */ : 0) | (end >= to ? 2 /* Open.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 /* Tree.BranchShift */ - 1)) && + updated.lines > (totalLines >> (5 /* Tree.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); + } + scanIdentical(other, dir) { + if (!(other instanceof TextNode)) + return 0; + let length = 0; + let [iA, iB, eA, eB] = dir > 0 ? [0, 0, this.children.length, other.children.length] + : [this.children.length - 1, other.children.length - 1, -1, -1]; + for (;; iA += dir, iB += dir) { + if (iA == eA || iB == eB) + return length; + let chA = this.children[iA], chB = other.children[iB]; + if (chA != chB) + return length + chA.scanIdentical(chB, dir); + length += chA.length + 1; + } + } + 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 /* Tree.Branch */) { + let flat = []; + for (let ch of children) + ch.flatten(flat); + return new TextLeaf(flat, length); + } + let chunk = Math.max(32 /* Tree.Branch */, lines >> 5 /* Tree.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 /* Tree.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 = /*@__PURE__*/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 ? 1 : (text instanceof TextLeaf ? text.text.length : text.children.length) << 1]; + } + nextInner(skip, dir) { + this.done = this.lineBreak = false; + for (;;) { + let last = this.nodes.length - 1; + let top = this.nodes[last], offsetValue = this.offsets[last], offset = offsetValue >> 1; + let size = top instanceof TextLeaf ? top.text.length : top.children.length; + if (offset == (dir > 0 ? size : 0)) { + if (last == 0) { + this.done = true; + this.value = ""; + return this; + } + if (dir > 0) + this.offsets[last - 1]++; + this.nodes.pop(); + this.offsets.pop(); + } + else if ((offsetValue & 1) == (dir > 0 ? 0 : 1)) { + this.offsets[last] += dir; + if (skip == 0) { + this.lineBreak = true; + this.value = "\n"; + return this; + } + skip--; + } + else if (top instanceof TextLeaf) { + // Move to the next string + let next = top.text[offset + (dir < 0 ? -1 : 0)]; + this.offsets[last] += dir; + if (next.length > Math.max(0, skip)) { + this.value = skip == 0 ? next : dir > 0 ? next.slice(skip) : next.slice(0, next.length - skip); + return this; + } + skip -= next.length; + } + else { + let next = top.children[offset + (dir < 0 ? -1 : 0)]; + if (skip > next.length) { + skip -= next.length; + this.offsets[last] += dir; + } + else { + if (dir < 0) + this.offsets[last]--; + this.nodes.push(next); + this.offsets.push(dir > 0 ? 1 : (next instanceof TextLeaf ? next.text.length : next.children.length) << 1); + } + } + } + } + next(skip = 0) { + if (skip < 0) { + this.nextInner(-skip, (-this.dir)); + skip = this.value.length; + } + return this.nextInner(skip, this.dir); + } + } + class PartialTextCursor { + constructor(text, start, end) { + this.value = ""; + this.done = false; + this.cursor = new RawTextCursor(text, start > end ? -1 : 1); + this.pos = start > end ? text.length : 0; + this.from = Math.min(start, end); + this.to = Math.max(start, end); + } + nextInner(skip, dir) { + if (dir < 0 ? this.pos <= this.from : this.pos >= this.to) { + this.value = ""; + this.done = true; + return this; + } + skip += Math.max(0, dir < 0 ? this.pos - this.to : this.from - this.pos); + let limit = dir < 0 ? this.pos - this.from : this.to - this.pos; + if (skip > limit) + skip = limit; + limit -= skip; + let { value } = this.cursor.next(skip); + this.pos += (value.length + skip) * dir; + this.value = value.length <= limit ? value : dir < 0 ? value.slice(value.length - limit) : value.slice(0, limit); + this.done = !this.value; + return this; + } + next(skip = 0) { + if (skip < 0) + skip = Math.max(skip, this.from - this.pos); + else if (skip > 0) + skip = Math.min(skip, this.to - this.pos); + return this.nextInner(skip, this.cursor.dir); + } + get lineBreak() { return this.cursor.lineBreak && this.value != ""; } + } + class LineCursor { + constructor(inner) { + this.inner = inner; + this.afterBreak = true; + this.value = ""; + this.done = false; + } + next(skip = 0) { + let { done, lineBreak, value } = this.inner.next(skip); + if (done) { + this.done = true; + this.value = ""; + } + else if (lineBreak) { + if (this.afterBreak) { + this.value = ""; + } + else { + this.afterBreak = true; + this.next(); + } + } + else { + this.value = value; + this.afterBreak = false; + } + return this; + } + get lineBreak() { return false; } + } + if (typeof Symbol != "undefined") { + Text.prototype[Symbol.iterator] = function () { return this.iter(); }; + RawTextCursor.prototype[Symbol.iterator] = PartialTextCursor.prototype[Symbol.iterator] = + LineCursor.prototype[Symbol.iterator] = function () { return this; }; + } + /** + This type describes a line in the document. It is created + on-demand when lines are [queried](https://codemirror.net/6/docs/ref/#state.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; } + } + + // 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 = /*@__PURE__*/"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 (when + `includeExtending` is true), characters joined with zero-width + joiners, and flag emoji. + */ + function findClusterBreak(str, pos, forward = true, includeExtending = true) { + return (forward ? nextClusterBreak : prevClusterBreak)(str, pos, includeExtending); + } + function nextClusterBreak(str, pos, includeExtending) { + 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 || includeExtending && 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, includeExtending) { + while (pos > 0) { + let found = nextClusterBreak(str, pos - 2, includeExtending); + 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 amount of positions a character takes up a JavaScript string. + */ + function codePointSize(code) { return code < 0x10000 ? 1 : 2; } + + const DefaultSplit = /\r\n?|\n/; + /** + Distinguishes different ways in which positions can be mapped. + */ + var MapMode = /*@__PURE__*/(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"; + return MapMode})(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. `posA` + provides the position of the range in the old document, `posB` + the new position in the changed document. + */ + 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.) + `fromA`/`toA` provides the extent of the change in the starting + document, `fromB`/`toB` the extent of the replacement in the + changed document. + + 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); + } + /** + @internal + */ + static create(sections) { return new ChangeDesc(sections); } + } + /** + 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 { + 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, with the range in the original document (`fromA`-`toA`) + and the range that replaces it in the new document + (`fromB`-`toB`). + + 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 ChangeDesc.create(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: ChangeDesc.create(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); + } + /** + @internal + */ + static createSet(sections, inserted) { + 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) { + // Produce a copy of setA that applies to the document after setB + // has been applied (assuming both start at the same document). + let sections = [], insert = mkSet ? [] : null; + let a = new SectionIter(setA), b = new SectionIter(setB); + // Iterate over both sets in parallel. inserted tracks, for changes + // in A that have to be processed piece-by-piece, whether their + // content has been inserted already, and refers to the section + // index. + for (let inserted = -1;;) { + if (a.ins == -1 && b.ins == -1) { + // Move across ranges skipped by both sets. + let len = Math.min(a.len, b.len); + addSection(sections, len, -1); + a.forward(len); + b.forward(len); + } + else if (b.ins >= 0 && (a.ins < 0 || inserted == a.i || a.off == 0 && (b.len < a.len || b.len == a.len && !before))) { + // If there's a change in B that comes before the next change in + // A (ordered by start pos, then len, then before flag), skip + // that (and process any changes in A it covers). + let len = b.len; + addSection(sections, b.ins, -1); + while (len) { + let piece = Math.min(a.len, len); + if (a.ins >= 0 && inserted < a.i && a.len <= piece) { + addSection(sections, 0, a.ins); + if (insert) + addInsert(insert, sections, a.text); + inserted = a.i; + } + a.forward(piece); + len -= piece; + } + b.next(); + } + else if (a.ins >= 0) { + // Process the part of a change in A up to the start of the next + // non-deletion change in B (if overlapping). + let len = 0, left = a.len; + while (left) { + if (b.ins == -1) { + let piece = Math.min(left, b.len); + len += piece; + left -= piece; + b.forward(piece); + } + else if (b.ins == 0 && b.len < left) { + left -= b.len; + b.next(); + } + else { + break; + } + } + addSection(sections, len, inserted < a.i ? a.ins : 0); + if (insert && inserted < a.i) + addInsert(insert, sections, a.text); + inserted = a.i; + a.forward(a.len - left); + } + else if (a.done && b.done) { + return insert ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(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 ? ChangeSet.createSet(sections, insert) : ChangeDesc.create(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 { + 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 /* RangeFlag.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 /* RangeFlag.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 /* RangeFlag.AssocBefore */ ? -1 : this.flags & 8 /* RangeFlag.AssocAfter */ ? 1 : 0; } + /** + The bidirectional text level associated with this cursor, if + any. + */ + get bidiLevel() { + let level = this.flags & 3 /* RangeFlag.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 /* RangeFlag.GoalColumnOffset */; + return value == 33554431 /* RangeFlag.NoGoalColumn */ ? undefined : value; + } + /** + Map this range through a change, producing a valid range in the + updated document. + */ + map(change, assoc = -1) { + let from, to; + if (this.empty) { + from = to = change.mapPos(this.from, assoc); + } + else { + from = change.mapPos(this.from, 1); + to = change.mapPos(this.to, -1); + } + 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); + } + /** + @internal + */ + static create(from, to, flags) { + return new SelectionRange(from, to, flags); + } + } + /** + An editor selection holds one or more selection ranges. + */ + class EditorSelection { + 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) { + 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], 0); + } + /** + 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 EditorSelection.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 SelectionRange.create(pos, pos, (assoc == 0 ? 0 : assoc < 0 ? 4 /* RangeFlag.AssocBefore */ : 8 /* RangeFlag.AssocAfter */) | + (bidiLevel == null ? 3 : Math.min(2, bidiLevel)) | + ((goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* RangeFlag.NoGoalColumn */) << 5 /* RangeFlag.GoalColumnOffset */)); + } + /** + Create a selection range. + */ + static range(anchor, head, goalColumn) { + let goal = (goalColumn !== null && goalColumn !== void 0 ? goalColumn : 33554431 /* RangeFlag.NoGoalColumn */) << 5 /* RangeFlag.GoalColumnOffset */; + return head < anchor ? SelectionRange.create(head, anchor, 16 /* RangeFlag.Inverted */ | goal | 8 /* RangeFlag.AssocAfter */) + : SelectionRange.create(anchor, head, goal | (head > anchor ? 4 /* RangeFlag.AssocBefore */ : 0)); + } + /** + @internal + */ + static 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 uses of facets are the [tab + size](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize), [editor + attributes](https://codemirror.net/6/docs/ref/#view.EditorView^editorAttributes), and [update + listeners](https://codemirror.net/6/docs/ref/#view.EditorView^updateListener). + */ + class Facet { + constructor( + /** + @internal + */ + combine, + /** + @internal + */ + compareInput, + /** + @internal + */ + compare, isStatic, enables) { + this.combine = combine; + this.compareInput = compareInput; + this.compare = compare; + this.isStatic = isStatic; + /** + @internal + */ + this.id = nextID++; + this.default = combine([]); + this.extensions = typeof enables == "function" ? enables(this) : enables; + } + /** + 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 to this facet. + */ + of(value) { + return new FacetProvider([], this, 0 /* Provider.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 cases where your value depends only on a single field, you'll + want to use the [`from`](https://codemirror.net/6/docs/ref/#state.Facet.from) method instead. + */ + compute(deps, get) { + if (this.isStatic) + throw new Error("Can't compute a static facet"); + return new FacetProvider(deps, this, 1 /* Provider.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 /* Provider.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 id = this.id, idx = addresses[id] >> 1, multi = this.type == 2 /* Provider.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 { + create(state) { + state.values[idx] = getter(state); + return 1 /* SlotStatus.Changed */; + }, + update(state, tr) { + if ((depDoc && tr.docChanged) || (depSel && (tr.docChanged || tr.selection)) || ensureAll(state, depAddrs)) { + let newVal = getter(state); + if (multi ? !compareArray(newVal, state.values[idx], compare) : !compare(newVal, state.values[idx])) { + state.values[idx] = newVal; + return 1 /* SlotStatus.Changed */; + } + } + return 0; + }, + reconfigure: (state, oldState) => { + let newVal = getter(state); + let oldAddr = oldState.config.address[id]; + if (oldAddr != null) { + let oldVal = getAddr(oldState, oldAddr); + if (this.dependencies.every(dep => { + return dep instanceof Facet ? oldState.facet(dep) === state.facet(dep) : + dep instanceof StateField ? oldState.field(dep, false) == state.field(dep, false) : true; + }) || (multi ? compareArray(newVal, oldVal, compare) : compare(newVal, oldVal))) { + state.values[idx] = oldVal; + return 0; + } + } + state.values[idx] = newVal; + return 1 /* SlotStatus.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 ensureAll(state, addrs) { + let changed = false; + for (let addr of addrs) + if (ensureAddr(state, addr) & 1 /* SlotStatus.Changed */) + changed = true; + return changed; + } + 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; + function get(state) { + let values = []; + for (let i = 0; i < providerAddrs.length; i++) { + let value = getAddr(state, providerAddrs[i]); + if (providerTypes[i] == 2 /* Provider.Multi */) + for (let val of value) + values.push(val); + else + values.push(value); + } + return facet.combine(values); + } + return { + create(state) { + for (let addr of providerAddrs) + ensureAddr(state, addr); + state.values[idx] = get(state); + return 1 /* SlotStatus.Changed */; + }, + update(state, tr) { + if (!ensureAll(state, dynamic)) + return 0; + let value = get(state); + if (facet.compare(value, state.values[idx])) + return 0; + state.values[idx] = value; + return 1 /* SlotStatus.Changed */; + }, + reconfigure(state, oldState) { + let depChanged = ensureAll(state, providerAddrs); + let oldProviders = oldState.config.facets[facet.id], oldValue = oldState.facet(facet); + if (oldProviders && !depChanged && sameArray$1(providers, oldProviders)) { + state.values[idx] = oldValue; + return 0; + } + let value = get(state); + if (facet.compare(value, oldValue)) { + state.values[idx] = oldValue; + return 0; + } + state.values[idx] = value; + return 1 /* SlotStatus.Changed */; + } + }; + } + const initField = /*@__PURE__*/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 { + create: (state) => { + state.values[idx] = this.create(state); + return 1 /* SlotStatus.Changed */; + }, + update: (state, tr) => { + let oldVal = state.values[idx]; + let value = this.updateF(oldVal, tr); + if (this.compareF(oldVal, value)) + return 0; + state.values[idx] = value; + return 1 /* SlotStatus.Changed */; + }, + reconfigure: (state, oldState) => { + if (oldState.config.address[this.id] != null) { + state.values[idx] = oldState.field(this); + return 0; + } + state.values[idx] = this.create(state); + return 1 /* SlotStatus.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_ = { lowest: 4, low: 3, default: 2, high: 1, highest: 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 = { + /** + The highest precedence level, for extensions that should end up + near the start of the precedence ordering. + */ + highest: /*@__PURE__*/prec(Prec_.highest), + /** + A higher-than-default precedence, for extensions that should + come before those with default precedence. + */ + high: /*@__PURE__*/prec(Prec_.high), + /** + The default precedence, which is also used for extensions + without an explicit precedence. + */ + default: /*@__PURE__*/prec(Prec_.default), + /** + A lower-than-default precedence. + */ + low: /*@__PURE__*/prec(Prec_.low), + /** + The lowest precedence level. Meant for things that should end up + near the end of the extension order. + */ + lowest: /*@__PURE__*/prec(Prec_.lowest) + }; + 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, facets) { + this.base = base; + this.compartments = compartments; + this.dynamicSlots = dynamicSlots; + this.address = address; + this.staticValues = staticValues; + this.facets = facets; + this.statusTemplate = []; + while (this.statusTemplate.length < dynamicSlots.length) + this.statusTemplate.push(0 /* SlotStatus.Unresolved */); + } + 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)); + } + let oldFacets = oldState === null || oldState === void 0 ? void 0 : oldState.config.facets; + for (let id in facets) { + let providers = facets[id], facet = providers[0].facet; + let oldProviders = oldFacets && oldFacets[id] || []; + if (providers.every(p => p.type == 0 /* Provider.Static */)) { + address[facet.id] = (staticValues.length << 1) | 1; + if (sameArray$1(oldProviders, providers)) { + staticValues.push(oldState.facet(facet)); + } + else { + let value = facet.combine(providers.map(p => p.value)); + staticValues.push(oldState && facet.compare(value, oldState.facet(facet)) ? oldState.facet(facet) : value); + } + } + else { + for (let p of providers) { + if (p.type == 0 /* Provider.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)); + } + } + let dynamic = dynamicSlots.map(f => f(address)); + return new Configuration(base, newCompartments, dynamic, address, staticValues, facets); + } + } + 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_.default); + } + 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 /* SlotStatus.Computed */; + let idx = addr >> 1; + let status = state.status[idx]; + if (status == 4 /* SlotStatus.Computing */) + throw new Error("Cyclic dependency between fields and/or facets"); + if (status & 2 /* SlotStatus.Computed */) + return status; + state.status[idx] = 4 /* SlotStatus.Computing */; + let changed = state.computeSlot(state, state.config.dynamicSlots[idx]); + return state.status[idx] = 2 /* SlotStatus.Computed */ | changed; + } + function getAddr(state, addr) { + return addr & 1 ? state.config.staticValues[addr >> 1] : state.values[addr >> 1]; + } + + const languageData = /*@__PURE__*/Facet.define(); + const allowMultipleSelections = /*@__PURE__*/Facet.define({ + combine: values => values.some(v => v), + static: true + }); + const lineSeparator = /*@__PURE__*/Facet.define({ + combine: values => values.length ? values[0] : undefined, + static: true + }); + const changeFilter = /*@__PURE__*/Facet.define(); + const transactionFilter = /*@__PURE__*/Facet.define(); + const transactionExtender = /*@__PURE__*/Facet.define(); + const readOnly = /*@__PURE__*/Facet.define({ + combine: values => values.length ? values[0] : false + }); + + /** + 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 = /*@__PURE__*/StateEffect.define(); + /** + Append extensions to the top-level configuration of the editor. + */ + StateEffect.appendConfig = /*@__PURE__*/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), or immediately + dispatch one by calling + [`EditorView.dispatch`](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch). + */ + class Transaction { + 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())); + } + /** + @internal + */ + static create(startState, changes, selection, effects, annotations, scrollIntoView) { + return new Transaction(startState, changes, selection, effects, annotations, scrollIntoView); + } + /** + 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 it is 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; } + /** + Returns true if the transaction has a [user + event](https://codemirror.net/6/docs/ref/#state.Transaction^userEvent) annotation that is equal to + or more specific than `event`. For example, if the transaction + has `"select.pointer"` as user event, `"select"` and + `"select.pointer"` will match it. + */ + isUserEvent(event) { + let e = this.annotation(Transaction.userEvent); + return !!(e && (e == event || e.length > event.length && e.slice(0, event.length) == event && e[event.length] == ".")); + } + } + /** + Annotation used to store transaction timestamps. Automatically + added to every transaction, holding `Date.now()`. + */ + Transaction.time = /*@__PURE__*/Annotation.define(); + /** + Annotation used to associate a transaction with a user interface + event. Holds a string identifying the event, using a + dot-separated format to support attaching more specific + information. The events used by the core libraries are: + + - `"input"` when content is entered + - `"input.type"` for typed input + - `"input.type.compose"` for composition + - `"input.paste"` for pasted input + - `"input.drop"` when adding content with drag-and-drop + - `"input.complete"` when autocompleting + - `"delete"` when the user deletes content + - `"delete.selection"` when deleting the selection + - `"delete.forward"` when deleting forward from the selection + - `"delete.backward"` when deleting backward from the selection + - `"delete.cut"` when cutting to the clipboard + - `"move"` when content is moved + - `"move.drop"` when content is moved within the editor through drag-and-drop + - `"select"` when explicitly changing the selection + - `"select.pointer"` when selecting with a mouse or other pointing device + - `"undo"` and `"redo"` for history actions + + Use [`isUserEvent`](https://codemirror.net/6/docs/ref/#state.Transaction.isUserEvent) to check + whether the annotation matches a given event. + */ + Transaction.userEvent = /*@__PURE__*/Annotation.define(); + /** + Annotation indicating whether a transaction should be added to + the undo history or not. + */ + Transaction.addToHistory = /*@__PURE__*/Annotation.define(); + /** + Annotation indicating (when present and true) that a transaction + represents a change made by some other actor, not the user. This + is used, for example, to tag other people's changes in + collaborative editing. + */ + Transaction.remote = /*@__PURE__*/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, annotations = asArray$1(spec.annotations); + if (spec.userEvent) + annotations = annotations.concat(Transaction.userEvent.of(spec.userEvent)); + 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$1(spec.effects), + 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 = Transaction.create(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.mapDesc(filtered.changes).invertedDesc; + } + tr = Transaction.create(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$1(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(spec, resolveTransactionInner(state, extension, tr.changes.newLength), true); + } + return spec == tr ? tr : Transaction.create(state, tr.changes, tr.selection, spec.effects, spec.annotations, spec.scrollIntoView); + } + const none$2 = []; + function asArray$1(value) { + return value == null ? none$2 : 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 = /*@__PURE__*/(function (CharCategory) { + /** + Word characters. + */ + CharCategory[CharCategory["Word"] = 0] = "Word"; + /** + Whitespace. + */ + CharCategory[CharCategory["Space"] = 1] = "Space"; + /** + Anything else. + */ + CharCategory[CharCategory["Other"] = 2] = "Other"; + return CharCategory})(CharCategory || (CharCategory = {})); + const nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + let wordChar; + try { + wordChar = /*@__PURE__*/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 { + constructor( + /** + @internal + */ + config, + /** + The current document. + */ + doc, + /** + The current selection. + */ + selection, + /** + @internal + */ + values, computeSlot, tr) { + this.config = config; + this.doc = doc; + this.selection = selection; + this.values = values; + this.status = config.statusTemplate.slice(); + this.computeSlot = computeSlot; + // 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.computeSlot = 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$1(base).concat(effect.value); + } + } + let startValues; + if (!conf) { + conf = Configuration.resolve(base, compartments, this); + let intermediateState = new EditorState(conf, this.doc, this.selection, conf.dynamicSlots.map(() => null), (state, slot) => slot.reconfigure(state, this), null); + startValues = intermediateState.values; + } + else { + startValues = tr.startState.values.slice(); + } + new EditorState(conf, tr.newDoc, tr.newSelection, startValues, (state, slot) => slot.update(state, tr), 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$1(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$1(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/#state.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 && this.config.address[value.id] != null) + 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) { + if (Object.prototype.hasOwnProperty.call(json, prop)) { + 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, configuration.dynamicSlots.map(() => null), (state, slot) => slot.create(state), null); + } + /** + 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"; } + /** + Returns true when the editor is + [configured](https://codemirror.net/6/docs/ref/#state.EditorState^readOnly) to be read-only. + */ + get readOnly() { return this.facet(readOnly); } + /** + 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. + + If additional arguments are passed, they will be inserted in + place of markers like `$1` (for the first value) and `$2`, etc. + A single `$` is equivalent to `$1`, and `$$` will produce a + literal dollar sign. + */ + phrase(phrase, ...insert) { + for (let map of this.facet(EditorState.phrases)) + if (Object.prototype.hasOwnProperty.call(map, phrase)) { + phrase = map[phrase]; + break; + } + if (insert.length) + phrase = phrase.replace(/\$(\$|\d*)/g, (m, i) => { + if (i == "$") + return "$"; + let n = +(i || 1); + return !n || n > insert.length ? m : insert[n - 1]; + }); + 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, side = -1) { + let values = []; + for (let provider of this.facet(languageData)) { + for (let result of provider(this, pos, side)) { + 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/#state.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("")); + } + /** + Find the word at the given position, meaning the range + containing all [word](https://codemirror.net/6/docs/ref/#state.CharCategory.Word) characters + around it. If no word characters are adjacent to the position, + this returns null. + */ + wordAt(pos) { + let { text, from, length } = this.doc.lineAt(pos); + let cat = this.charCategorizer(pos); + let start = pos - from, end = pos - from; + while (start > 0) { + let prev = findClusterBreak(text, start, false); + if (cat(text.slice(prev, start)) != CharCategory.Word) + break; + start = prev; + } + while (end < length) { + let next = findClusterBreak(text, end); + if (cat(text.slice(end, next)) != CharCategory.Word) + break; + end = next; + } + return start == end ? null : EditorSelection.range(start + from, end + from); + } + } + /** + 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 = /*@__PURE__*/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; + /** + This facet controls the value of the + [`readOnly`](https://codemirror.net/6/docs/ref/#state.EditorState.readOnly) getter, which is + consulted by commands and extensions that implement editing + functionality to determine whether they should apply. It + defaults to false, but when its highest-precedence value is + `true`, such functionality disables itself. + + Not to be confused with + [`EditorView.editable`](https://codemirror.net/6/docs/ref/#view.EditorView^editable), which + controls whether the editor's DOM is set to be editable (and + thus focusable). + */ + EditorState.readOnly = readOnly; + /** + 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 = /*@__PURE__*/Facet.define({ + compare(a, b) { + let kA = Object.keys(a), kB = Object.keys(b); + return kA.length == kB.length && kA.every(k => a[k] == b[k]); + } + }); + /** + 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 numbers 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 transaction spec (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 if 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 present. + */ + EditorState.transactionExtender = transactionExtender; + Compartment.reconfigure = /*@__PURE__*/StateEffect.define(); + + /** + Utility function for combining behaviors to fill in a config + object from an array of provided configs. `defaults` should hold + default values for all optional fields in `Config`. + + The function 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; + } + + /** + Each range is associated with a value, which must inherit from + this class. + */ + class RangeValue { + /** + Compare this value with another value. Used when comparing + rangesets. The default implementation compares by identity. + Unless you are only creating a fixed number of unique instances + of your value type, it is a good idea to implement this + properly. + */ + eq(other) { return this == other; } + /** + Create a [range](https://codemirror.net/6/docs/ref/#state.Range) with this value. + */ + range(from, to = from) { return Range$1.create(from, to, this); } + } + RangeValue.prototype.startSide = RangeValue.prototype.endSide = 0; + RangeValue.prototype.point = false; + RangeValue.prototype.mapMode = MapMode.TrackDel; + /** + A range associates a value with a range of positions. + */ + class Range$1 { + constructor( + /** + The range's start position. + */ + from, + /** + Its end position. + */ + to, + /** + The value associated with this range. + */ + value) { + this.from = from; + this.to = to; + this.value = value; + } + /** + @internal + */ + static create(from, to, value) { + return new Range$1(from, to, value); + } + } + function cmpRange(a, b) { + return a.from - b.from || a.value.startSide - b.value.startSide; + } + class Chunk { + constructor(from, to, value, + // Chunks are marked with the largest point that occurs + // in them (or -1 for no points), so that scans that are + // only interested in points (such as the + // heightmap-related logic) can skip range-only chunks. + maxPoint) { + this.from = from; + this.to = to; + this.value = value; + this.maxPoint = maxPoint; + } + get length() { return this.to[this.to.length - 1]; } + // Find the index of the given position and side. Use the ranges' + // `from` pos when `end == false`, `to` when `end == true`. + findIndex(pos, side, end, startAt = 0) { + let arr = end ? this.to : this.from; + for (let lo = startAt, hi = arr.length;;) { + if (lo == hi) + return lo; + let mid = (lo + hi) >> 1; + let diff = arr[mid] - pos || (end ? this.value[mid].endSide : this.value[mid].startSide) - side; + if (mid == lo) + return diff >= 0 ? lo : hi; + if (diff >= 0) + hi = mid; + else + lo = mid + 1; + } + } + between(offset, from, to, f) { + for (let i = this.findIndex(from, -1000000000 /* C.Far */, true), e = this.findIndex(to, 1000000000 /* C.Far */, false, i); i < e; i++) + if (f(this.from[i] + offset, this.to[i] + offset, this.value[i]) === false) + return false; + } + map(offset, changes) { + let value = [], from = [], to = [], newPos = -1, maxPoint = -1; + for (let i = 0; i < this.value.length; i++) { + let val = this.value[i], curFrom = this.from[i] + offset, curTo = this.to[i] + offset, newFrom, newTo; + if (curFrom == curTo) { + let mapped = changes.mapPos(curFrom, val.startSide, val.mapMode); + if (mapped == null) + continue; + newFrom = newTo = mapped; + if (val.startSide != val.endSide) { + newTo = changes.mapPos(curFrom, val.endSide); + if (newTo < newFrom) + continue; + } + } + else { + newFrom = changes.mapPos(curFrom, val.startSide); + newTo = changes.mapPos(curTo, val.endSide); + if (newFrom > newTo || newFrom == newTo && val.startSide > 0 && val.endSide <= 0) + continue; + } + if ((newTo - newFrom || val.endSide - val.startSide) < 0) + continue; + if (newPos < 0) + newPos = newFrom; + if (val.point) + maxPoint = Math.max(maxPoint, newTo - newFrom); + value.push(val); + from.push(newFrom - newPos); + to.push(newTo - newPos); + } + return { mapped: value.length ? new Chunk(from, to, value, maxPoint) : null, pos: newPos }; + } + } + /** + A range set stores a collection of [ranges](https://codemirror.net/6/docs/ref/#state.Range) in a + way that makes them efficient to [map](https://codemirror.net/6/docs/ref/#state.RangeSet.map) and + [update](https://codemirror.net/6/docs/ref/#state.RangeSet.update). This is an immutable data + structure. + */ + class RangeSet { + constructor( + /** + @internal + */ + chunkPos, + /** + @internal + */ + chunk, + /** + @internal + */ + nextLayer, + /** + @internal + */ + maxPoint) { + this.chunkPos = chunkPos; + this.chunk = chunk; + this.nextLayer = nextLayer; + this.maxPoint = maxPoint; + } + /** + @internal + */ + static create(chunkPos, chunk, nextLayer, maxPoint) { + return new RangeSet(chunkPos, chunk, nextLayer, maxPoint); + } + /** + @internal + */ + get length() { + let last = this.chunk.length - 1; + return last < 0 ? 0 : Math.max(this.chunkEnd(last), this.nextLayer.length); + } + /** + The number of ranges in the set. + */ + get size() { + if (this.isEmpty) + return 0; + let size = this.nextLayer.size; + for (let chunk of this.chunk) + size += chunk.value.length; + return size; + } + /** + @internal + */ + chunkEnd(index) { + return this.chunkPos[index] + this.chunk[index].length; + } + /** + Update the range set, optionally adding new ranges or filtering + out existing ones. + + (Note: The type parameter is just there as a kludge to work + around TypeScript variance issues that prevented `RangeSet` + from being a subtype of `RangeSet` when `X` is a subtype of + `Y`.) + */ + update(updateSpec) { + let { add = [], sort = false, filterFrom = 0, filterTo = this.length } = updateSpec; + let filter = updateSpec.filter; + if (add.length == 0 && !filter) + return this; + if (sort) + add = add.slice().sort(cmpRange); + if (this.isEmpty) + return add.length ? RangeSet.of(add) : this; + let cur = new LayerCursor(this, null, -1).goto(0), i = 0, spill = []; + let builder = new RangeSetBuilder(); + while (cur.value || i < add.length) { + if (i < add.length && (cur.from - add[i].from || cur.startSide - add[i].value.startSide) >= 0) { + let range = add[i++]; + if (!builder.addInner(range.from, range.to, range.value)) + spill.push(range); + } + else if (cur.rangeIndex == 1 && cur.chunkIndex < this.chunk.length && + (i == add.length || this.chunkEnd(cur.chunkIndex) < add[i].from) && + (!filter || filterFrom > this.chunkEnd(cur.chunkIndex) || filterTo < this.chunkPos[cur.chunkIndex]) && + builder.addChunk(this.chunkPos[cur.chunkIndex], this.chunk[cur.chunkIndex])) { + cur.nextChunk(); + } + else { + if (!filter || filterFrom > cur.to || filterTo < cur.from || filter(cur.from, cur.to, cur.value)) { + if (!builder.addInner(cur.from, cur.to, cur.value)) + spill.push(Range$1.create(cur.from, cur.to, cur.value)); + } + cur.next(); + } + } + return builder.finishInner(this.nextLayer.isEmpty && !spill.length ? RangeSet.empty + : this.nextLayer.update({ add: spill, filter, filterFrom, filterTo })); + } + /** + Map this range set through a set of changes, return the new set. + */ + map(changes) { + if (changes.empty || this.isEmpty) + return this; + let chunks = [], chunkPos = [], maxPoint = -1; + for (let i = 0; i < this.chunk.length; i++) { + let start = this.chunkPos[i], chunk = this.chunk[i]; + let touch = changes.touchesRange(start, start + chunk.length); + if (touch === false) { + maxPoint = Math.max(maxPoint, chunk.maxPoint); + chunks.push(chunk); + chunkPos.push(changes.mapPos(start)); + } + else if (touch === true) { + let { mapped, pos } = chunk.map(start, changes); + if (mapped) { + maxPoint = Math.max(maxPoint, mapped.maxPoint); + chunks.push(mapped); + chunkPos.push(pos); + } + } + } + let next = this.nextLayer.map(changes); + return chunks.length == 0 ? next : new RangeSet(chunkPos, chunks, next || RangeSet.empty, maxPoint); + } + /** + Iterate over the ranges that touch the region `from` to `to`, + calling `f` for each. There is no guarantee that the ranges will + be reported in any specific order. When the callback returns + `false`, iteration stops. + */ + between(from, to, f) { + if (this.isEmpty) + return; + for (let i = 0; i < this.chunk.length; i++) { + let start = this.chunkPos[i], chunk = this.chunk[i]; + if (to >= start && from <= start + chunk.length && + chunk.between(start, from - start, to - start, f) === false) + return; + } + this.nextLayer.between(from, to, f); + } + /** + Iterate over the ranges in this set, in order, including all + ranges that end at or after `from`. + */ + iter(from = 0) { + return HeapCursor.from([this]).goto(from); + } + /** + @internal + */ + get isEmpty() { return this.nextLayer == this; } + /** + Iterate over the ranges in a collection of sets, in order, + starting from `from`. + */ + static iter(sets, from = 0) { + return HeapCursor.from(sets).goto(from); + } + /** + Iterate over two groups of sets, calling methods on `comparator` + to notify it of possible differences. + */ + static compare(oldSets, newSets, + /** + This indicates how the underlying data changed between these + ranges, and is needed to synchronize the iteration. `from` and + `to` are coordinates in the _new_ space, after these changes. + */ + textDiff, comparator, + /** + Can be used to ignore all non-point ranges, and points below + the given size. When -1, all ranges are compared. + */ + minPointSize = -1) { + let a = oldSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize); + let b = newSets.filter(set => set.maxPoint > 0 || !set.isEmpty && set.maxPoint >= minPointSize); + let sharedChunks = findSharedChunks(a, b, textDiff); + let sideA = new SpanCursor(a, sharedChunks, minPointSize); + let sideB = new SpanCursor(b, sharedChunks, minPointSize); + textDiff.iterGaps((fromA, fromB, length) => compare(sideA, fromA, sideB, fromB, length, comparator)); + if (textDiff.empty && textDiff.length == 0) + compare(sideA, 0, sideB, 0, 0, comparator); + } + /** + Compare the contents of two groups of range sets, returning true + if they are equivalent in the given range. + */ + static eq(oldSets, newSets, from = 0, to) { + if (to == null) + to = 1000000000 /* C.Far */; + let a = oldSets.filter(set => !set.isEmpty && newSets.indexOf(set) < 0); + let b = newSets.filter(set => !set.isEmpty && oldSets.indexOf(set) < 0); + if (a.length != b.length) + return false; + if (!a.length) + return true; + let sharedChunks = findSharedChunks(a, b); + let sideA = new SpanCursor(a, sharedChunks, 0).goto(from), sideB = new SpanCursor(b, sharedChunks, 0).goto(from); + for (;;) { + if (sideA.to != sideB.to || + !sameValues(sideA.active, sideB.active) || + sideA.point && (!sideB.point || !sideA.point.eq(sideB.point))) + return false; + if (sideA.to > to) + return true; + sideA.next(); + sideB.next(); + } + } + /** + Iterate over a group of range sets at the same time, notifying + the iterator about the ranges covering every given piece of + content. Returns the open count (see + [`SpanIterator.span`](https://codemirror.net/6/docs/ref/#state.SpanIterator.span)) at the end + of the iteration. + */ + static spans(sets, from, to, iterator, + /** + When given and greater than -1, only points of at least this + size are taken into account. + */ + minPointSize = -1) { + let cursor = new SpanCursor(sets, null, minPointSize).goto(from), pos = from; + let open = cursor.openStart; + for (;;) { + let curTo = Math.min(cursor.to, to); + if (cursor.point) { + iterator.point(pos, curTo, cursor.point, cursor.activeForPoint(cursor.to), open, cursor.pointRank); + open = cursor.openEnd(curTo) + (cursor.to > curTo ? 1 : 0); + } + else if (curTo > pos) { + iterator.span(pos, curTo, cursor.active, open); + open = cursor.openEnd(curTo); + } + if (cursor.to > to) + break; + pos = cursor.to; + cursor.next(); + } + return open; + } + /** + Create a range set for the given range or array of ranges. By + default, this expects the ranges to be _sorted_ (by start + position and, if two start at the same position, + `value.startSide`). You can pass `true` as second argument to + cause the method to sort them. + */ + static of(ranges, sort = false) { + let build = new RangeSetBuilder(); + for (let range of ranges instanceof Range$1 ? [ranges] : sort ? lazySort(ranges) : ranges) + build.add(range.from, range.to, range.value); + return build.finish(); + } + } + /** + The empty set of ranges. + */ + RangeSet.empty = /*@__PURE__*/new RangeSet([], [], null, -1); + function lazySort(ranges) { + if (ranges.length > 1) + for (let prev = ranges[0], i = 1; i < ranges.length; i++) { + let cur = ranges[i]; + if (cmpRange(prev, cur) > 0) + return ranges.slice().sort(cmpRange); + prev = cur; + } + return ranges; + } + RangeSet.empty.nextLayer = RangeSet.empty; + /** + A range set builder is a data structure that helps build up a + [range set](https://codemirror.net/6/docs/ref/#state.RangeSet) directly, without first allocating + an array of [`Range`](https://codemirror.net/6/docs/ref/#state.Range) objects. + */ + class RangeSetBuilder { + /** + Create an empty builder. + */ + constructor() { + this.chunks = []; + this.chunkPos = []; + this.chunkStart = -1; + this.last = null; + this.lastFrom = -1000000000 /* C.Far */; + this.lastTo = -1000000000 /* C.Far */; + this.from = []; + this.to = []; + this.value = []; + this.maxPoint = -1; + this.setMaxPoint = -1; + this.nextLayer = null; + } + finishChunk(newArrays) { + this.chunks.push(new Chunk(this.from, this.to, this.value, this.maxPoint)); + this.chunkPos.push(this.chunkStart); + this.chunkStart = -1; + this.setMaxPoint = Math.max(this.setMaxPoint, this.maxPoint); + this.maxPoint = -1; + if (newArrays) { + this.from = []; + this.to = []; + this.value = []; + } + } + /** + Add a range. Ranges should be added in sorted (by `from` and + `value.startSide`) order. + */ + add(from, to, value) { + if (!this.addInner(from, to, value)) + (this.nextLayer || (this.nextLayer = new RangeSetBuilder)).add(from, to, value); + } + /** + @internal + */ + addInner(from, to, value) { + let diff = from - this.lastTo || value.startSide - this.last.endSide; + if (diff <= 0 && (from - this.lastFrom || value.startSide - this.last.startSide) < 0) + throw new Error("Ranges must be added sorted by `from` position and `startSide`"); + if (diff < 0) + return false; + if (this.from.length == 250 /* C.ChunkSize */) + this.finishChunk(true); + if (this.chunkStart < 0) + this.chunkStart = from; + this.from.push(from - this.chunkStart); + this.to.push(to - this.chunkStart); + this.last = value; + this.lastFrom = from; + this.lastTo = to; + this.value.push(value); + if (value.point) + this.maxPoint = Math.max(this.maxPoint, to - from); + return true; + } + /** + @internal + */ + addChunk(from, chunk) { + if ((from - this.lastTo || chunk.value[0].startSide - this.last.endSide) < 0) + return false; + if (this.from.length) + this.finishChunk(true); + this.setMaxPoint = Math.max(this.setMaxPoint, chunk.maxPoint); + this.chunks.push(chunk); + this.chunkPos.push(from); + let last = chunk.value.length - 1; + this.last = chunk.value[last]; + this.lastFrom = chunk.from[last] + from; + this.lastTo = chunk.to[last] + from; + return true; + } + /** + Finish the range set. Returns the new set. The builder can't be + used anymore after this has been called. + */ + finish() { return this.finishInner(RangeSet.empty); } + /** + @internal + */ + finishInner(next) { + if (this.from.length) + this.finishChunk(false); + if (this.chunks.length == 0) + return next; + let result = RangeSet.create(this.chunkPos, this.chunks, this.nextLayer ? this.nextLayer.finishInner(next) : next, this.setMaxPoint); + this.from = null; // Make sure further `add` calls produce errors + return result; + } + } + function findSharedChunks(a, b, textDiff) { + let inA = new Map(); + for (let set of a) + for (let i = 0; i < set.chunk.length; i++) + if (set.chunk[i].maxPoint <= 0) + inA.set(set.chunk[i], set.chunkPos[i]); + let shared = new Set(); + for (let set of b) + for (let i = 0; i < set.chunk.length; i++) { + let known = inA.get(set.chunk[i]); + if (known != null && (textDiff ? textDiff.mapPos(known) : known) == set.chunkPos[i] && + !(textDiff === null || textDiff === void 0 ? void 0 : textDiff.touchesRange(known, known + set.chunk[i].length))) + shared.add(set.chunk[i]); + } + return shared; + } + class LayerCursor { + constructor(layer, skip, minPoint, rank = 0) { + this.layer = layer; + this.skip = skip; + this.minPoint = minPoint; + this.rank = rank; + } + get startSide() { return this.value ? this.value.startSide : 0; } + get endSide() { return this.value ? this.value.endSide : 0; } + goto(pos, side = -1000000000 /* C.Far */) { + this.chunkIndex = this.rangeIndex = 0; + this.gotoInner(pos, side, false); + return this; + } + gotoInner(pos, side, forward) { + while (this.chunkIndex < this.layer.chunk.length) { + let next = this.layer.chunk[this.chunkIndex]; + if (!(this.skip && this.skip.has(next) || + this.layer.chunkEnd(this.chunkIndex) < pos || + next.maxPoint < this.minPoint)) + break; + this.chunkIndex++; + forward = false; + } + if (this.chunkIndex < this.layer.chunk.length) { + let rangeIndex = this.layer.chunk[this.chunkIndex].findIndex(pos - this.layer.chunkPos[this.chunkIndex], side, true); + if (!forward || this.rangeIndex < rangeIndex) + this.setRangeIndex(rangeIndex); + } + this.next(); + } + forward(pos, side) { + if ((this.to - pos || this.endSide - side) < 0) + this.gotoInner(pos, side, true); + } + next() { + for (;;) { + if (this.chunkIndex == this.layer.chunk.length) { + this.from = this.to = 1000000000 /* C.Far */; + this.value = null; + break; + } + else { + let chunkPos = this.layer.chunkPos[this.chunkIndex], chunk = this.layer.chunk[this.chunkIndex]; + let from = chunkPos + chunk.from[this.rangeIndex]; + this.from = from; + this.to = chunkPos + chunk.to[this.rangeIndex]; + this.value = chunk.value[this.rangeIndex]; + this.setRangeIndex(this.rangeIndex + 1); + if (this.minPoint < 0 || this.value.point && this.to - this.from >= this.minPoint) + break; + } + } + } + setRangeIndex(index) { + if (index == this.layer.chunk[this.chunkIndex].value.length) { + this.chunkIndex++; + if (this.skip) { + while (this.chunkIndex < this.layer.chunk.length && this.skip.has(this.layer.chunk[this.chunkIndex])) + this.chunkIndex++; + } + this.rangeIndex = 0; + } + else { + this.rangeIndex = index; + } + } + nextChunk() { + this.chunkIndex++; + this.rangeIndex = 0; + this.next(); + } + compare(other) { + return this.from - other.from || this.startSide - other.startSide || this.rank - other.rank || + this.to - other.to || this.endSide - other.endSide; + } + } + class HeapCursor { + constructor(heap) { + this.heap = heap; + } + static from(sets, skip = null, minPoint = -1) { + let heap = []; + for (let i = 0; i < sets.length; i++) { + for (let cur = sets[i]; !cur.isEmpty; cur = cur.nextLayer) { + if (cur.maxPoint >= minPoint) + heap.push(new LayerCursor(cur, skip, minPoint, i)); + } + } + return heap.length == 1 ? heap[0] : new HeapCursor(heap); + } + get startSide() { return this.value ? this.value.startSide : 0; } + goto(pos, side = -1000000000 /* C.Far */) { + for (let cur of this.heap) + cur.goto(pos, side); + for (let i = this.heap.length >> 1; i >= 0; i--) + heapBubble(this.heap, i); + this.next(); + return this; + } + forward(pos, side) { + for (let cur of this.heap) + cur.forward(pos, side); + for (let i = this.heap.length >> 1; i >= 0; i--) + heapBubble(this.heap, i); + if ((this.to - pos || this.value.endSide - side) < 0) + this.next(); + } + next() { + if (this.heap.length == 0) { + this.from = this.to = 1000000000 /* C.Far */; + this.value = null; + this.rank = -1; + } + else { + let top = this.heap[0]; + this.from = top.from; + this.to = top.to; + this.value = top.value; + this.rank = top.rank; + if (top.value) + top.next(); + heapBubble(this.heap, 0); + } + } + } + function heapBubble(heap, index) { + for (let cur = heap[index];;) { + let childIndex = (index << 1) + 1; + if (childIndex >= heap.length) + break; + let child = heap[childIndex]; + if (childIndex + 1 < heap.length && child.compare(heap[childIndex + 1]) >= 0) { + child = heap[childIndex + 1]; + childIndex++; + } + if (cur.compare(child) < 0) + break; + heap[childIndex] = cur; + heap[index] = child; + index = childIndex; + } + } + class SpanCursor { + constructor(sets, skip, minPoint) { + this.minPoint = minPoint; + this.active = []; + this.activeTo = []; + this.activeRank = []; + this.minActive = -1; + // A currently active point range, if any + this.point = null; + this.pointFrom = 0; + this.pointRank = 0; + this.to = -1000000000 /* C.Far */; + this.endSide = 0; + this.openStart = -1; + this.cursor = HeapCursor.from(sets, skip, minPoint); + } + goto(pos, side = -1000000000 /* C.Far */) { + this.cursor.goto(pos, side); + this.active.length = this.activeTo.length = this.activeRank.length = 0; + this.minActive = -1; + this.to = pos; + this.endSide = side; + this.openStart = -1; + this.next(); + return this; + } + forward(pos, side) { + while (this.minActive > -1 && (this.activeTo[this.minActive] - pos || this.active[this.minActive].endSide - side) < 0) + this.removeActive(this.minActive); + this.cursor.forward(pos, side); + } + removeActive(index) { + remove(this.active, index); + remove(this.activeTo, index); + remove(this.activeRank, index); + this.minActive = findMinIndex(this.active, this.activeTo); + } + addActive(trackOpen) { + let i = 0, { value, to, rank } = this.cursor; + while (i < this.activeRank.length && this.activeRank[i] <= rank) + i++; + insert(this.active, i, value); + insert(this.activeTo, i, to); + insert(this.activeRank, i, rank); + if (trackOpen) + insert(trackOpen, i, this.cursor.from); + this.minActive = findMinIndex(this.active, this.activeTo); + } + // After calling this, if `this.point` != null, the next range is a + // point. Otherwise, it's a regular range, covered by `this.active`. + next() { + let from = this.to, wasPoint = this.point; + this.point = null; + let trackOpen = this.openStart < 0 ? [] : null, trackExtra = 0; + for (;;) { + let a = this.minActive; + if (a > -1 && (this.activeTo[a] - this.cursor.from || this.active[a].endSide - this.cursor.startSide) < 0) { + if (this.activeTo[a] > from) { + this.to = this.activeTo[a]; + this.endSide = this.active[a].endSide; + break; + } + this.removeActive(a); + if (trackOpen) + remove(trackOpen, a); + } + else if (!this.cursor.value) { + this.to = this.endSide = 1000000000 /* C.Far */; + break; + } + else if (this.cursor.from > from) { + this.to = this.cursor.from; + this.endSide = this.cursor.startSide; + break; + } + else { + let nextVal = this.cursor.value; + if (!nextVal.point) { // Opening a range + this.addActive(trackOpen); + if (this.cursor.from < from && this.cursor.to > from) + trackExtra++; + this.cursor.next(); + } + else if (wasPoint && this.cursor.to == this.to && this.cursor.from < this.cursor.to) { + // Ignore any non-empty points that end precisely at the end of the prev point + this.cursor.next(); + } + else { // New point + this.point = nextVal; + this.pointFrom = this.cursor.from; + this.pointRank = this.cursor.rank; + this.to = this.cursor.to; + this.endSide = nextVal.endSide; + if (this.cursor.from < from) + trackExtra = 1; + this.cursor.next(); + this.forward(this.to, this.endSide); + break; + } + } + } + if (trackOpen) { + let openStart = 0; + while (openStart < trackOpen.length && trackOpen[openStart] < from) + openStart++; + this.openStart = openStart + trackExtra; + } + } + activeForPoint(to) { + if (!this.active.length) + return this.active; + let active = []; + for (let i = this.active.length - 1; i >= 0; i--) { + if (this.activeRank[i] < this.pointRank) + break; + if (this.activeTo[i] > to || this.activeTo[i] == to && this.active[i].endSide >= this.point.endSide) + active.push(this.active[i]); + } + return active.reverse(); + } + openEnd(to) { + let open = 0; + for (let i = this.activeTo.length - 1; i >= 0 && this.activeTo[i] > to; i--) + open++; + return open; + } + } + function compare(a, startA, b, startB, length, comparator) { + a.goto(startA); + b.goto(startB); + let endB = startB + length; + let pos = startB, dPos = startB - startA; + for (;;) { + let diff = (a.to + dPos) - b.to || a.endSide - b.endSide; + let end = diff < 0 ? a.to + dPos : b.to, clipEnd = Math.min(end, endB); + if (a.point || b.point) { + if (!(a.point && b.point && (a.point == b.point || a.point.eq(b.point)) && + sameValues(a.activeForPoint(a.to + dPos), b.activeForPoint(b.to)))) + comparator.comparePoint(pos, clipEnd, a.point, b.point); + } + else { + if (clipEnd > pos && !sameValues(a.active, b.active)) + comparator.compareRange(pos, clipEnd, a.active, b.active); + } + if (end > endB) + break; + pos = end; + if (diff <= 0) + a.next(); + if (diff >= 0) + b.next(); + } + } + function sameValues(a, b) { + if (a.length != b.length) + return false; + for (let i = 0; i < a.length; i++) + if (a[i] != b[i] && !a[i].eq(b[i])) + return false; + return true; + } + function remove(array, index) { + for (let i = index, e = array.length - 1; i < e; i++) + array[i] = array[i + 1]; + array.pop(); + } + function insert(array, index, value) { + for (let i = array.length - 1; i >= index; i--) + array[i + 1] = array[i]; + array[index] = value; + } + function findMinIndex(value, array) { + let found = -1, foundPos = 1000000000 /* C.Far */; + for (let i = 0; i < array.length; i++) + if ((array[i] - foundPos || value[i].endSide - value[found].endSide) < 0) { + found = i; + foundPos = array[i]; + } + return found; + } + + /** + Count the column position at the given offset into the string, + taking extending characters and tab size into account. + */ + function countColumn(string, tabSize, to = string.length) { + let n = 0; + for (let i = 0; i < to;) { + 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. By + default, the string length is returned when it is too short to + reach the column. Pass `strict` true to make it return -1 in that + situation. + */ + function findColumn(string, col, tabSize, strict) { + for (let i = 0, n = 0;;) { + if (n >= col) + return i; + if (i == string.length) + break; + n += string.charCodeAt(i) == 9 ? tabSize - (n % tabSize) : 1; + i = findClusterBreak(string, i); + } + return strict === true ? -1 : string.length; + } + + 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